(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[974],{1206:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>e4});var n=r(973),a=r(8361);let i=(...e)=>e.filter((e,t,r)=>!!e&&""!==e.trim()&&r.indexOf(e)===t).join(" ").trim(),s=e=>{let t=e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,r)=>r?r.toUpperCase():t.toLowerCase());return t.charAt(0).toUpperCase()+t.slice(1)};var o={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let l=(0,a.forwardRef)(({color:e="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:n,className:s="",children:l,iconNode:c,...d},u)=>(0,a.createElement)("svg",{ref:u,...o,width:t,height:t,stroke:e,strokeWidth:n?24*Number(r)/Number(t):r,className:i("lucide",s),...!l&&!(e=>{for(let t in e)if(t.startsWith("aria-")||"role"===t||"title"===t)return!0;return!1})(d)&&{"aria-hidden":"true"},...d},[...c.map(([e,t])=>(0,a.createElement)(e,t)),...Array.isArray(l)?l:[l]])),c=(e,t)=>{let r=(0,a.forwardRef)(({className:r,...n},o)=>(0,a.createElement)(l,{ref:o,iconNode:t,className:i(`lucide-${s(e).replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}`,`lucide-${e}`,r),...n}));return r.displayName=s(e),r},d=c("book-open",[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]]),u=c("book-text",[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20",key:"k3hazp"}],["path",{d:"M8 11h8",key:"vwpz6n"}],["path",{d:"M8 7h6",key:"1f0q6e"}]]),m=c("pencil-line",[["path",{d:"M13 21h8",key:"1jsn5i"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}],["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}]]),p=c("headphones",[["path",{d:"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3",key:"1xhozi"}]]),g=c("mic",[["path",{d:"M12 19v3",key:"npa21l"}],["path",{d:"M19 10v2a7 7 0 0 1-14 0v-2",key:"1vc78b"}],["rect",{x:"9",y:"2",width:"6",height:"13",rx:"3",key:"s6n7sd"}]]),f=c("refresh-cw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]),h=c("square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]),y=c("play",[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]]);var w=r(943);let b=[{key:"voca",label:"Voca",description:"Add, review, and rotate your personal IELTS-focused vocabulary cards.",icon:d},{key:"reading",label:"Reading",description:"Expand to passage analysis, inference skills, and faster question solving.",icon:u},{key:"writing",label:"Writing",description:"Practice IELTS Task 2 prompts, draft stronger essays, and receive focused feedback.",icon:m},{key:"listening",label:"Listening",description:"Expand to audio comprehension, detail capture, and practical note-taking.",icon:p},{key:"speaking",label:"Speaking",description:"Expand to fluency, coherence, lexical range, and confident delivery.",icon:g}],x="https://wpa5awwucc.execute-api.us-east-2.amazonaws.com/prod/voca",v="https://5rr3o0eovi.execute-api.us-east-2.amazonaws.com/prod/meaning",S="https://ife0wvqkx8.execute-api.us-east-2.amazonaws.com/prod/reading/create",j="https://cvgkcfgmj3.execute-api.us-east-2.amazonaws.com/prod/reading/get",k=w.env.NEXT_PUBLIC_READING_ENDPOINT,N="https://6pixmyz624.execute-api.us-east-2.amazonaws.com/prod/writing/create",A="https://1oc1y84aoj.execute-api.us-east-2.amazonaws.com/prod/writing/get",$="https://12cb3kwfmh.execute-api.us-east-2.amazonaws.com/prod/writing/score",R="https://bbrldo12v3.execute-api.us-east-2.amazonaws.com/prod/listening/create",D="https://55f7p6c132.execute-api.us-east-2.amazonaws.com/prod/listening/get",T="https://ew9861sazd.execute-api.us-east-2.amazonaws.com/prod/speaking/create",P="https://s390jmmfki.execute-api.us-east-2.amazonaws.com/prod/speaking/get",H="https://oro1dx9sji.execute-api.us-east-2.amazonaws.com/prod/speaking/score",C="voca-store",M="reading-solved-history",E="writing-solved-history",L="writing-task-session",I="listening-solved-history",q="speaking-solved-history",O="speaking-task-session",F="ielts-formelog-writing-score-cooldown-until",z="ielts-formelog-speaking-score-cooldown-until",U="ielts-formelog-speaking-stt-debug",K="text-[clamp(1.25rem,4.6vw,2.4rem)]",W=["Magazine","Journal","Book","Newspaper","Environment","History","Science","Psychology"],B=["en-GB","en-AU","en-US","en-CA"],_=["male","man","david","daniel","james","tom","guy","mark","john","ryan","andrew","christopher","eric","brian","roger","aaron","arthur","davis","george","jacob","liam","neerja","onyx","echo"],V=["female","woman","zira","susan","samantha","victoria","karen","hazel","emma","aria","jenny","michelle","ana","natasha","libby","sonia","ava","alloy","nova","shimmer"],J=null,G=null;function Y(e){let t=String(e.getSeconds()).padStart(2,"0"),r=String(e.getMinutes()).padStart(2,"0"),n=String(e.getHours()).padStart(2,"0"),a=String(e.getDate()).padStart(2,"0"),i=String(e.getMonth()+1).padStart(2,"0"),s=String(e.getFullYear()).slice(-2);return`${t}${r}${n}${a}${i}${s}`}function Z(e){if(!e||"object"!=typeof e)return null;let t=Array.isArray(e.questions)?e.questions.filter(e=>"string"==typeof e&&e.trim().length>0):[],r=Array.isArray(e.answers)?e.answers.filter(e=>"string"==typeof e&&e.trim().length>0):[],n="string"==typeof e.passage?e.passage.trim():"";return n&&0!==t.length&&0!==r.length?{id:"string"==typeof e.id&&e.id.trim().length>0?e.id:`reading-${Date.now()}`,field:"string"==typeof e.field&&e.field.trim().length>0?e.field:"General Academic",dataSetHash:"string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?e.dataSetHash.trim().toLowerCase():void 0,generatedAtKey:"string"==typeof e.generatedAtKey&&e.generatedAtKey.trim().length>0?e.generatedAtKey:Y(new Date),reverseTimeKey:"string"==typeof e.reverseTimeKey&&e.reverseTimeKey.trim().length>0?e.reverseTimeKey:void 0,passage:n,questions:t.slice(0,12),answers:r.slice(0,12)}:null}function Q(e){if(!e||"object"!=typeof e)return null;let t=Array.isArray(e.questions)?e.questions.filter(e=>"string"==typeof e&&e.trim().length>0):[],r=Array.isArray(e.answers)?e.answers.filter(e=>"string"==typeof e&&e.trim().length>0):[],n=("string"==typeof e.script?e.script:"string"==typeof e.listeningPassage?e.listeningPassage:"string"==typeof e.passage?e.passage:"").trim();return n&&0!==t.length&&0!==r.length?{id:"string"==typeof e.id&&e.id.trim().length>0?e.id:`listening-${Date.now()}`,field:"string"==typeof e.field&&e.field.trim().length>0?e.field:"General Listening",dataSetHash:"string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?e.dataSetHash.trim().toLowerCase():void 0,generatedAtKey:"string"==typeof e.generatedAtKey&&e.generatedAtKey.trim().length>0?e.generatedAtKey:Y(new Date),reverseTimeKey:"string"==typeof e.reverseTimeKey&&e.reverseTimeKey.trim().length>0?e.reverseTimeKey:void 0,script:n,questions:t.slice(0,10),answers:r.slice(0,10)}:null}function X(e){if(!e||"object"!=typeof e)return null;let t=("string"==typeof e.topic?e.topic:"string"==typeof e.prompt?e.prompt:"string"==typeof e.writingTask2?e.writingTask2:"string"==typeof e.question?e.question:"string"==typeof e.task2?e.task2:"").trim(),r=("string"==typeof e.modelAnswer?e.modelAnswer:"string"==typeof e.exemplarAnswer?e.exemplarAnswer:"").trim(),n=("string"==typeof e.topicField?e.topicField:"string"==typeof e.field?e.field:"string"==typeof e.category?e.category:"").trim();return t?{id:"string"==typeof e.id&&e.id.trim().length>0?e.id:`writing-${Date.now()}`,topicField:n||"Writing Prompt",topic:t,modelAnswer:r||void 0,dataSetHash:"string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?e.dataSetHash.trim().toLowerCase():void 0,generatedAtKey:"string"==typeof e.generatedAtKey&&e.generatedAtKey.trim().length>0?e.generatedAtKey:Y(new Date),reverseTimeKey:"string"==typeof e.reverseTimeKey&&e.reverseTimeKey.trim().length>0?e.reverseTimeKey:void 0}:null}function ee(e){if(!e||"object"!=typeof e)return null;let t="number"==typeof e.score||"string"==typeof e.score?e.score:"number"==typeof e.bandScore||"string"==typeof e.bandScore?e.bandScore:"number"==typeof e.totalScore||"string"==typeof e.totalScore?e.totalScore:null,r=null===t?"":String(t).trim(),n=(Array.isArray(e.comments)?e.comments:Array.isArray(e.commentList)?e.commentList:Array.isArray(e.feedback)?e.feedback:[]).filter(e=>"string"==typeof e&&e.trim().length>0);return r&&0!==n.length?{score:r,comments:n}:null}function et(e){if(!e||"object"!=typeof e)return null;let t=(()=>{let t=e.speakingPart2;if("string"==typeof t)return t;if(!t||"object"!=typeof t)return"";let r="string"==typeof t.topicSentence?t.topicSentence.trim():"",n=Array.isArray(t.bulletPrompts)?t.bulletPrompts.filter(e=>"string"==typeof e&&e.trim().length>0).map(e=>e.trim()).slice(0,4):[],a="string"==typeof t.finalInstruction&&t.finalInstruction.trim().length>0?t.finalInstruction.trim():"Now, please talk about this for 1-2 minutes.";return r?[r,"You should say:",...n.map(e=>`- ${e}`),a].join("\n").trim():""})(),r=("string"==typeof e.topic?e.topic:"string"==typeof e.prompt?e.prompt:"string"==typeof e.speakingPart2?e.speakingPart2:t).trim(),n=("string"==typeof e.modelAnswer?e.modelAnswer:"string"==typeof e.exemplarAnswer?e.exemplarAnswer:"").trim(),a=("string"==typeof e.topicField?e.topicField:"string"==typeof e.field?e.field:"string"==typeof e.category?e.category:"").trim();return r?{id:"string"==typeof e.id&&e.id.trim().length>0?e.id:`speaking-${Date.now()}`,topicField:a||"Speaking Part 2",topic:r,modelAnswer:n||void 0,dataSetHash:"string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?e.dataSetHash.trim().toLowerCase():void 0,generatedAtKey:"string"==typeof e.generatedAtKey&&e.generatedAtKey.trim().length>0?e.generatedAtKey:Y(new Date),reverseTimeKey:"string"==typeof e.reverseTimeKey&&e.reverseTimeKey.trim().length>0?e.reverseTimeKey:void 0}:null}function er(e){if(!e||"object"!=typeof e||!e.scores||"object"!=typeof e.scores||!e.comments||"object"!=typeof e.comments)return null;let t=e.scores,r=e.comments,n={fluencyAndCoherence:"",lexicalResource:"",grammaticalRangeAndAccuracy:"",pronunciation:""},a={fluencyAndCoherence:[],lexicalResource:[],grammaticalRangeAndAccuracy:[],pronunciation:[]};for(let e of["fluencyAndCoherence","lexicalResource","grammaticalRangeAndAccuracy","pronunciation"]){let i=String(t[e]??"").trim(),s=Array.isArray(r[e])?r[e].filter(e=>"string"==typeof e&&e.trim().length>0):[];if(!i||0===s.length)return null;n[e]=i,a[e]=s}return{scores:n,comments:a}}function en(e){return e.trim().split(/\s+/).filter(Boolean).length}function ea(){"speechSynthesis"in window&&window.speechSynthesis.cancel()}function ei(e,t){let r=/[\uac00-\ud7a3]/.test(e),n=/[A-Za-z]/.test(e);return r&&!n?"ko-KR":n&&!r?"en-US":r?"ko-KR":n?"en-US":t||"en-US"}function es(e){let t=e.trim().toLowerCase();return 0===t.length?"":`${t[0].toUpperCase()}${t.slice(1)}`}async function eo(e,t){if(!v)return null;let r=await fetch(v,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:e,targetLanguage:t})});if(!r.ok)return null;let n=await r.json();return"string"==typeof n.meaning&&n.meaning.trim().length>0?n.meaning.trim():null}function el(e){return"number"==typeof e.id?`id-${e.id}`:`${e.voca}-${e.yymmdd}-${e.createdAt}`}function ec(e){return"string"==typeof e&&e.includes("|")}function ed(e){return e.split("|").map(e=>e.trim()).filter(e=>e.length>0).join("\n").split("\n").map(e=>e.trim()).filter(e=>e.length>0).map(e=>{let t=e.indexOf(":");return t<=0?{label:"",value:e}:{label:e.slice(0,t).trim(),value:e.slice(t+1).trim()}})}function eu(e){return e.replace(/^\s*\d+\)\s*/,"").trim()}function em(e){let t=String(e.getFullYear()).slice(-2),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`}function ep(e){if(!/^\d{6}$/.test(e))return null;let t=Number(e.slice(0,2)),r=Number(e.slice(2,4)),n=Number(e.slice(4,6));if(!Number.isInteger(t)||!Number.isInteger(r)||!Number.isInteger(n)||r<1||r>12||n<1||n>31)return null;let a=new Date(2e3+t,r-1,n);return a.getMonth()+1!==r||a.getDate()!==n?null:a}function eg(e){let t,r=e.filter(e=>"string"==typeof e?.yymmdd&&null!==ep(e.yymmdd)).sort((e,t)=>e.yymmdd!==t.yymmdd?e.yymmdd.localeCompare(t.yymmdd):e.createdAt-t.createdAt)[0];return r?((t=ep(r.yymmdd))?(t.setDate(t.getDate()-1),em(t)):null)??em(new Date):em(new Date)}function ef(){return new Promise((e,t)=>{let r=indexedDB.open("ielts-formelog-db",6);r.onupgradeneeded=()=>{let e=r.result;e.objectStoreNames.contains(C)||e.createObjectStore(C,{keyPath:"id",autoIncrement:!0}).createIndex("byDate","yymmdd",{unique:!1}),e.objectStoreNames.contains(M)||e.createObjectStore(M,{keyPath:"id"}),e.objectStoreNames.contains(E)||e.createObjectStore(E,{keyPath:"id"}),e.objectStoreNames.contains(L)||e.createObjectStore(L,{keyPath:"id"}),e.objectStoreNames.contains(I)||e.createObjectStore(I,{keyPath:"id"}),e.objectStoreNames.contains(q)||e.createObjectStore(q,{keyPath:"id"}),e.objectStoreNames.contains(O)||e.createObjectStore(O,{keyPath:"id"})},r.onsuccess=()=>e(r.result),r.onerror=()=>t(r.error)})}function eh(e){return e.trim().toLowerCase()}function ey(e){return e.trim().toLowerCase()}function ew(e){return e.trim().toLowerCase()}function eb(e){return e.trim().toLowerCase()}function ex(e){let t=e.trim();return 0===t.length||/automatic speech-to-text output was unavailable/i.test(t)}function ev(e){return`hash#${ew(e)}`}function eS(e){return`hash#${eb(e)}`}function ej(e){window.localStorage.setItem(F,String(e))}function ek(e,t,r){let n=e.getItem(t);if("string"==typeof n&&n.trim().length>0)return n;let a="u">typeof crypto&&"function"==typeof crypto.randomUUID?`${r}-${crypto.randomUUID()}`:`${r}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;return e.setItem(t,a),a}function eN(){let e={"Content-Type":"application/json"};try{e["x-formelog-device-id"]=ek(window.localStorage,"ielts-formelog-score-device-id","dev"),e["x-formelog-browser-id"]=ek(window.localStorage,"ielts-formelog-score-browser-id","browser"),e["x-formelog-session-id"]=ek(window.sessionStorage,"ielts-formelog-score-session-id","sess")}catch{}return e}function eA(e){window.localStorage.setItem(z,String(e))}function e$(e,t){return"string"==typeof e.dataSetHash&&0!==e.dataSetHash.trim().length&&new Set(t.map(e=>eh(e.dataSetHash))).has(eh(e.dataSetHash))}async function eR(){let e=await ef(),t=await new Promise((t,r)=>{let n=e.transaction(M,"readonly").objectStore(M).getAll();n.onsuccess=()=>{t((n.result??[]).filter(e=>"string"==typeof e?.dataSetHash&&e.dataSetHash.trim().length>0).map(e=>({dataSetHash:eh(e.dataSetHash)})))},n.onerror=()=>r(n.error)});return e.close(),t}async function eD(e){let t="string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?eh(e.dataSetHash):void 0;if(!t)return;let r=await ef();await new Promise((e,n)=>{let a=r.transaction(M,"readwrite"),i=a.objectStore(M),s=`hash#${t}`;i.put({id:s,dataSetHash:t,solvedAt:Date.now()}),a.oncomplete=()=>e(),a.onerror=()=>n(a.error)}),r.close()}async function eT(){let e=await ef();await new Promise((t,r)=>{let n=e.transaction(M,"readwrite").objectStore(M).clear();n.onsuccess=()=>t(),n.onerror=()=>r(n.error)}),e.close()}function eP(e,t){return"string"==typeof e.dataSetHash&&0!==e.dataSetHash.trim().length&&new Set(t.map(e=>ew(e.dataSetHash))).has(ew(e.dataSetHash))}async function eH(){let e=await ef(),t=await new Promise((t,r)=>{let n=e.transaction(E,"readonly").objectStore(E).getAll();n.onsuccess=()=>{t((n.result??[]).filter(e=>"string"==typeof e?.dataSetHash&&e.dataSetHash.trim().length>0).map(e=>({dataSetHash:ew(e.dataSetHash)})))},n.onerror=()=>r(n.error)});return e.close(),t}async function eC(e){let t="string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?ew(e.dataSetHash):void 0;if(!t)return;let r=await ef();await new Promise((e,n)=>{let a=r.transaction(E,"readwrite"),i=a.objectStore(E),s=`hash#${t}`;i.put({id:s,dataSetHash:t,solvedAt:Date.now()}),a.oncomplete=()=>e(),a.onerror=()=>n(a.error)}),r.close()}async function eM(){let e=await ef();await new Promise((t,r)=>{let n=e.transaction([E,L],"readwrite"),a=n.objectStore(E),i=n.objectStore(L);a.clear(),i.clear(),n.oncomplete=()=>t(),n.onerror=()=>r(n.error)}),e.close()}async function eE(e){let t=ew(e);if(!t)return null;let r=await ef(),n=await new Promise((e,n)=>{let a=r.transaction(L,"readonly").objectStore(L).get(ev(t));a.onsuccess=()=>{e(a.result??null)},a.onerror=()=>n(a.error)});return(r.close(),n&&ew(n.dataSetHash)===t)?{answer:"string"==typeof n.answer?n.answer:"",score:ee(n.score)}:null}async function eL(e,t){let r=ew(e);if(!r)return;let n="string"==typeof t.answer?t.answer:"",a=t.score?ee(t.score):null,i=await ef();await new Promise((e,t)=>{let s=i.transaction(L,"readwrite");s.objectStore(L).put({id:ev(r),dataSetHash:r,answer:n,score:a,updatedAt:Date.now()}),s.oncomplete=()=>e(),s.onerror=()=>t(s.error)}),i.close()}function eI(e,t){return"string"==typeof e.dataSetHash&&0!==e.dataSetHash.trim().length&&new Set(t.map(e=>ey(e.dataSetHash))).has(ey(e.dataSetHash))}async function eq(){let e=await ef(),t=await new Promise((t,r)=>{let n=e.transaction(I,"readonly").objectStore(I).getAll();n.onsuccess=()=>{t((n.result??[]).filter(e=>"string"==typeof e?.dataSetHash&&e.dataSetHash.trim().length>0).map(e=>({dataSetHash:ey(e.dataSetHash)})))},n.onerror=()=>r(n.error)});return e.close(),t}async function eO(e){let t="string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?ey(e.dataSetHash):void 0;if(!t)return;let r=await ef();await new Promise((e,n)=>{let a=r.transaction(I,"readwrite"),i=a.objectStore(I),s=`hash#${t}`;i.put({id:s,dataSetHash:t,solvedAt:Date.now()}),a.oncomplete=()=>e(),a.onerror=()=>n(a.error)}),r.close()}async function eF(){let e=await ef();await new Promise((t,r)=>{let n=e.transaction(I,"readwrite").objectStore(I).clear();n.onsuccess=()=>t(),n.onerror=()=>r(n.error)}),e.close()}function ez(e,t){return"string"==typeof e.dataSetHash&&0!==e.dataSetHash.trim().length&&new Set(t.map(e=>eb(e.dataSetHash))).has(eb(e.dataSetHash))}async function eU(){let e=await ef(),t=await new Promise((t,r)=>{let n=e.transaction(q,"readonly").objectStore(q).getAll();n.onsuccess=()=>{t((n.result??[]).filter(e=>"string"==typeof e?.dataSetHash&&e.dataSetHash.trim().length>0).map(e=>({dataSetHash:eb(e.dataSetHash)})))},n.onerror=()=>r(n.error)});return e.close(),t}async function eK(e){let t="string"==typeof e.dataSetHash&&e.dataSetHash.trim().length>0?eb(e.dataSetHash):void 0;if(!t)return;let r=await ef();await new Promise((e,n)=>{let a=r.transaction(q,"readwrite"),i=a.objectStore(q),s=`hash#${t}`;i.put({id:s,dataSetHash:t,solvedAt:Date.now()}),a.oncomplete=()=>e(),a.onerror=()=>n(a.error)}),r.close()}async function eW(){let e=await ef();await new Promise((t,r)=>{let n=e.transaction([q,O],"readwrite"),a=n.objectStore(q),i=n.objectStore(O);a.clear(),i.clear(),n.oncomplete=()=>t(),n.onerror=()=>r(n.error)}),e.close()}async function eB(e){let t=eb(e);if(!t)return null;let r=await ef(),n=await new Promise((e,n)=>{let a=r.transaction(O,"readonly").objectStore(O).get(eS(t));a.onsuccess=()=>{e(a.result??null)},a.onerror=()=>n(a.error)});if(r.close(),!n||eb(n.dataSetHash)!==t)return null;let a="string"==typeof n.audioDataUrl?n.audioDataUrl:"",i="string"==typeof n.audioMimeType?n.audioMimeType:"audio/webm",s=Number(n.audioDurationSec||0),o="string"==typeof n.transcript?n.transcript:"",l=er(n.score),c=ex(o);return a?{audioDataUrl:a,audioMimeType:i,audioDurationSec:Number.isFinite(s)?Math.max(0,s):0,transcript:c?"":o,score:c?null:l}:null}async function e_(e,t){let r=eb(e);if(!r)return;let n=await ef();await new Promise((e,a)=>{let i=n.transaction(O,"readwrite");i.objectStore(O).put({id:eS(r),dataSetHash:r,audioDataUrl:t.audioDataUrl,audioMimeType:t.audioMimeType,audioDurationSec:t.audioDurationSec,transcript:t.transcript||"",score:t.score?er(t.score):null,updatedAt:Date.now()}),i.oncomplete=()=>e(),i.onerror=()=>a(i.error)}),n.close()}async function eV(e=1200){if(!("speechSynthesis"in window))return[];let t=window.speechSynthesis,r=t.getVoices();if(r.length>0)return r;let n=Date.now();for(;Date.now()-n{window.setTimeout(e,150)});let e=t.getVoices();if(e.length>0)return e}return t.getVoices()}async function eJ(e){let t=await eV();if(0===t.length)return null;let r=e.toLowerCase().startsWith("en")?B:[e],n=e=>{let t=`${e.name} ${e.voiceURI}`.toLowerCase();return _.some(e=>t.includes(e))?"male":V.some(e=>t.includes(e))?"female":null},a=t.filter(e=>B.some(t=>e.lang.toLowerCase().startsWith(t.toLowerCase()))),i=t.filter(e=>e.lang.toLowerCase().startsWith("en")),s=a.length>0?a:i;if(0===s.length)return null;let o=.5>Math.random()?"male":"female",l=s.map(e=>{let t=e.lang.toLowerCase(),a=n(e)??"unknown",i=1;return r.some(e=>t.startsWith(e.toLowerCase()))?i+=6:t.startsWith("en")&&(i+=3),a===o&&(i+=4),G&&"unknown"!==a&&a!==G&&(i+=2),J&&e.voiceURI===J&&(i=Math.max(1,i-4)),{voice:e,gender:a,weight:i}}),c=l.reduce((e,t)=>e+t.weight,0);if(c<=0)return s[Math.floor(Math.random()*s.length)]??null;let d=Math.random()*c;for(let e of l)if((d-=e.weight)<=0)return J=e.voice.voiceURI,G=e.gender,e.voice;let u=s[Math.floor(Math.random()*s.length)]??null;if(u){let e=n(u);J=u.voiceURI,G=e??"unknown"}return u}async function eG(){let e=await ef();await new Promise((t,r)=>{let n=e.transaction(M,"readwrite"),a=n.objectStore(M),i=a.getAll();i.onsuccess=()=>{let e=Array.from(new Set((i.result??[]).map(e=>"string"==typeof e?.dataSetHash?eh(e.dataSetHash):"").filter(e=>e.length>0)));for(let t of(a.clear(),e))a.put({id:`hash#${t}`,dataSetHash:t,solvedAt:Date.now()})},n.oncomplete=()=>t(),n.onerror=()=>r(n.error)}),e.close()}async function eY(e){let t=es(e),r=await ef(),n=await new Promise((e,n)=>{let a=r.transaction(C,"readonly").objectStore(C).getAll();a.onsuccess=()=>{let r=a.result??[];e({exists:r.some(e=>es(e?.voca??"")===t),latestCreatedAt:r.reduce((e,t)=>"number"==typeof t?.createdAt&&t.createdAt>e?t.createdAt:e,0)})},a.onerror=()=>n(a.error)});if(n.exists||n.latestCreatedAt>0&&Date.now()-n.latestCreatedAt<1e3)return r.close(),!1;let a=eg(await new Promise((e,t)=>{let n=r.transaction(C,"readonly").objectStore(C).getAll();n.onsuccess=()=>{e(n.result??[])},n.onerror=()=>t(n.error)}));return await new Promise((e,n)=>{let i=r.transaction(C,"readwrite");i.objectStore(C).add({voca:t,yymmdd:a,createdAt:Date.now(),meaning:""}),i.oncomplete=()=>e(),i.onerror=()=>n(i.error)}),r.close(),!0}async function eZ(e){let t=es(e),r=await ef(),n=0;return await new Promise((e,a)=>{let i=r.transaction(C,"readwrite"),s=i.objectStore(C),o=s.getAll();o.onsuccess=()=>{let e=o.result??[],r=eg(e);for(let a of e.filter(e=>es(e?.voca??"")===t))"number"==typeof a?.id&&(s.put({...a,yymmdd:r}),n+=1)},o.onerror=()=>a(o.error),i.oncomplete=()=>e(),i.onerror=()=>a(i.error)}),r.close(),n>0}async function eQ(){let e=await ef(),t=await new Promise((t,r)=>{let n=e.transaction(C,"readonly").objectStore(C).getAll();n.onsuccess=()=>{t((n.result??[]).reduce((e,t)=>"number"==typeof t?.createdAt&&t.createdAt>e?t.createdAt:e,0))},n.onerror=()=>r(n.error)});return e.close(),0===t||Date.now()-t>=1e3}async function eX(e,t){if("number"!=typeof e.id)return;let r=await ef();await new Promise((n,a)=>{let i=r.transaction(C,"readwrite");i.objectStore(C).put({...e,yymmdd:em(new Date),createdAt:Date.now(),meaning:"string"==typeof t?t:e.meaning||""}),i.oncomplete=()=>n(),i.onerror=()=>a(i.error)}),r.close()}async function e0(e,t){if("number"!=typeof e.id)return;let r=await ef();await new Promise((n,a)=>{let i=r.transaction(C,"readwrite");i.objectStore(C).put({...e,meaning:t}),i.oncomplete=()=>n(),i.onerror=()=>a(i.error)}),r.close()}async function e1(e){let t=await ef();if("number"==typeof e.id){let r=e.id;return await new Promise((e,n)=>{let a=t.transaction(C,"readwrite");a.objectStore(C).delete(r),a.oncomplete=()=>e(),a.onerror=()=>n(a.error)}),t.close(),!0}let r=await new Promise((r,n)=>{let a=t.transaction(C,"readonly").objectStore(C).getAll();a.onsuccess=()=>{let t=(a.result??[]).find(t=>es(t.voca)===es(e.voca)&&t.yymmdd===e.yymmdd&&t.createdAt===e.createdAt);r("number"==typeof t?.id?t.id:null)},a.onerror=()=>n(a.error)});return null===r?(t.close(),!1):(await new Promise((e,n)=>{let a=t.transaction(C,"readwrite");a.objectStore(C).delete(r),a.oncomplete=()=>e(),a.onerror=()=>n(a.error)}),t.close(),!0)}async function e2(){let e=indexedDB;if("function"!=typeof e.databases)return;let t=(await e.databases()).map(e=>e?.name).filter(e=>"string"==typeof e&&e.startsWith("aws:cognito-identity"));await Promise.all(t.map(e=>new Promise(t=>{let r=indexedDB.deleteDatabase(e);r.onsuccess=()=>t(),r.onerror=()=>t(),r.onblocked=()=>t()})))}async function e3(){let e=await ef(),t=await new Promise((t,r)=>{let n=e.transaction(C,"readonly").objectStore(C).getAll();n.onsuccess=()=>{t((n.result??[]).filter(e=>"string"==typeof e?.voca&&"string"==typeof e?.yymmdd).sort((e,t)=>e.yymmdd!==t.yymmdd?e.yymmdd.localeCompare(t.yymmdd):e.createdAt-t.createdAt))},n.onerror=()=>r(n.error)});return e.close(),t}async function e5(){if(!x)return;let e=await ef();if(await new Promise((t,r)=>{let n=e.transaction(C,"readonly").objectStore(C).count();n.onsuccess=()=>t(n.result??0),n.onerror=()=>r(n.error)})>0)return void e.close();let t=await fetch(x,{method:"GET"});if(!t.ok)return void e.close();let r=await t.json(),n=(Array.isArray(r?.items)?r.items:[]).map(e=>{if(!e||"object"!=typeof e)return null;let t="string"==typeof e.voca?es(e.voca):"";return t?{voca:t}:null}).filter(e=>null!==e);if(0===n.length)return void e.close();let a=new Map;for(let e of n)a.set(e.voca,e);let i=Array.from(a.values()).sort((e,t)=>e.voca.localeCompare(t.voca)),s=Date.now();await new Promise((t,r)=>{let n=e.transaction(C,"readwrite"),a=n.objectStore(C);i.forEach((e,t)=>{let r=em(new Date);a.add({voca:e.voca,yymmdd:r,createdAt:s+t,meaning:""})}),n.oncomplete=()=>t(),n.onerror=()=>r(n.error)}),e.close()}function e4(){let[e,t]=(0,a.useState)(""),[r,i]=(0,a.useState)([]),[s,o]=(0,a.useState)([]),[l,c]=(0,a.useState)({}),[d,u]=(0,a.useState)({}),[m,p]=(0,a.useState)(!1),[g,w]=(0,a.useState)(!1),[v,C]=(0,a.useState)(""),[M,E]=(0,a.useState)("en"),[L,I]=(0,a.useState)(null),[q,O]=(0,a.useState)(""),[B,_]=(0,a.useState)(!1),[V,J]=(0,a.useState)(!1),[G,ep]=(0,a.useState)(null),[eg,ef]=(0,a.useState)(""),[eh,ey]=(0,a.useState)(!1),[eb,ev]=(0,a.useState)(""),[eS,ek]=(0,a.useState)(!1),[eV,e4]=(0,a.useState)(null),[e6,e9]=(0,a.useState)(0),[e8,e7]=(0,a.useState)(!1),[te,tt]=(0,a.useState)(null),[tr,tn]=(0,a.useState)(""),[ta,ti]=(0,a.useState)(!1),[ts,to]=(0,a.useState)(!1),[tl,tc]=(0,a.useState)(!1),[td,tu]=(0,a.useState)(!1),[tm,tp]=(0,a.useState)(null),[tg,tf]=(0,a.useState)(""),[th,ty]=(0,a.useState)(!1),[tw,tb]=(0,a.useState)(!1),[tx,tv]=(0,a.useState)(!1),[tS,tj]=(0,a.useState)(0),[tk,tN]=(0,a.useState)("idle"),[tA,t$]=(0,a.useState)(0),[tR,tD]=(0,a.useState)(0),[tT,tP]=(0,a.useState)(""),[tH,tC]=(0,a.useState)(0),[tM,tE]=(0,a.useState)("audio/webm"),[tL,tI]=(0,a.useState)(""),[tq,tO]=(0,a.useState)(!0),[tF,tz]=(0,a.useState)(!1),[,tU]=(0,a.useState)([]),[,tK]=(0,a.useState)({results:0,errors:0,ends:0,silentEnds:0,restarts:0,watchdogRestarts:0,lastError:"",lastErrorAtMs:0,lastResultAtMs:0}),[tW,tB]=(0,a.useState)(!1),[,t_]=(0,a.useState)(!1),[,tV]=(0,a.useState)(null),[,tJ]=(0,a.useState)(""),tG=(0,a.useMemo)(()=>!!x,[]),[tY,tZ]=(0,a.useState)(64),tQ=(0,a.useRef)(null),tX=(0,a.useRef)(null),t0=(0,a.useRef)(null),t1=(0,a.useRef)(null),t2=(0,a.useRef)(null),t3=(0,a.useRef)(0),t5=(0,a.useRef)(!1),t4=(0,a.useRef)([]),t6=(0,a.useRef)([]),t9=(0,a.useRef)(0),t8=(0,a.useRef)(!1),t7=(0,a.useRef)([]),re=(0,a.useRef)(!1),rt=(0,a.useRef)(0),rr=(0,a.useRef)(!1),rn=(0,a.useRef)([]),ra=(0,a.useRef)([]),ri=(0,a.useRef)(0),rs=(0,a.useRef)(!1),ro=(0,a.useRef)([]),rl=(0,a.useRef)(0),rc=(0,a.useRef)(!1),rd=(0,a.useRef)(null),ru=(0,a.useRef)(null),rm=(0,a.useRef)([]),rp=(0,a.useRef)(null),rg=(0,a.useRef)(null),rf=(0,a.useRef)(null),rh=(0,a.useRef)(null),ry=(0,a.useRef)(null),rw=(0,a.useRef)(async()=>{}),rb=(0,a.useRef)(()=>{}),rx=(0,a.useRef)(null),rv=(0,a.useRef)(0),rS=(0,a.useRef)(""),rj=(0,a.useRef)(!1),rk=(0,a.useRef)(null),rN=(0,a.useRef)(null),rA=(0,a.useRef)(""),r$=(0,a.useRef)([]),rR=(0,a.useRef)(0),rD=(0,a.useRef)(0),rT=(0,a.useRef)(0),rP=(0,a.useRef)(0),rH=(0,a.useRef)(0),rC=(0,a.useRef)(0),rM=(0,a.useRef)(0),rE=(0,a.useRef)(0),rL=(0,a.useRef)(!1),rI=(0,a.useRef)(0),rq=(0,a.useRef)(null),rO=(0,a.useRef)(0),rF=(0,a.useRef)(!1),rz=(0,a.useRef)(async()=>{}),rU=e=>{rS.current=e,tI(e)},rK=(0,a.useCallback)((e,t)=>{if(!tF)return;let r=new Date().toISOString().split("T")[1]?.replace("Z","")||"time-unknown",n=t&&t.trim().length>0?`${r} | ${e} | ${t}`:`${r} | ${e}`;tU(e=>{let t=[...e,n];return t.slice(Math.max(0,t.length-120))})},[tF]);(0,a.useEffect)(()=>{let e="1"===new URLSearchParams(window.location.search).get("sttDebug"),t="1"===window.localStorage.getItem(U);tz(e||t),e&&window.localStorage.setItem(U,"1"),tO(!0)},[]),(0,a.useEffect)(()=>{if(!tF)return;rK("debug.enabled",`secureContext=${String(window.isSecureContext)}`),rK("debug.ua",navigator.userAgent);let e=navigator.permissions;e?.query?e.query({name:"microphone"}).then(e=>{rK("debug.permission",`microphone=${e.state}`)}).catch(()=>{rK("debug.permission","microphone=query-failed")}):rK("debug.permission","microphone=permissions-api-unavailable")},[rK,tF]),(0,a.useEffect)(()=>{if(!tF)return;let e=()=>{rK("debug.visibility",document.visibilityState)},t=()=>{rK("debug.network","online")},r=()=>{rK("debug.network","offline")};return document.addEventListener("visibilitychange",e),window.addEventListener("online",t),window.addEventListener("offline",r),()=>{document.removeEventListener("visibilitychange",e),window.removeEventListener("online",t),window.removeEventListener("offline",r)}},[rK,tF]);let rW=(0,a.useRef)({}),rB=(0,a.useRef)({}),r_=(0,a.useMemo)(()=>b.filter(e=>"voca"!==e.key),[]),rV=(0,a.useCallback)(()=>{let e=tX.current;if(!e)return;e.style.height="auto";let t=Number.parseFloat(window.getComputedStyle(e).lineHeight||"24"),r=Number.isFinite(t)?2*t:48;e.style.height=`${e.scrollHeight+r}px`},[]),rJ=(0,a.useCallback)((e,t,r)=>{let n=[...e].sort((e,t)=>e.yymmdd!==t.yymmdd?e.yymmdd.localeCompare(t.yymmdd):e.createdAt-t.createdAt),a=t.length>0?t:n.slice(0,5),i=Array.from(new Set(n.map(e=>e.yymmdd))).sort((e,t)=>e.localeCompare(t)),s=[];for(let e of i){let t=5-s.length;if(t<=0)break;let i=n.filter(t=>t.yymmdd===e);if(0===i.length)continue;let o=new Map(i.map(e=>[el(e),e])),l=rB.current[e],c=Array.isArray(l)&&l.length===i.length&&l.every(e=>o.has(e))?l:function(e){let t=[...e];for(let e=t.length-1;e>0;e-=1){let r=Math.floor(Math.random()*(e+1)),n=t[e];t[e]=t[r],t[r]=n}return t}(i.map(e=>el(e)));rB.current[e]=c;let d=c.map(e=>o.get(e)).filter(e=>void 0!==e);if(d.length<=t){s.push(...d);continue}let u=a.find(t=>t.yymmdd===e),m=u?el(u):null,p=m?d.findIndex(e=>el(e)===m):-1,g=rW.current[e],f=Number.isInteger(g)?g:p>=0?p:0,h=Math.min(5,d.length),y=r&&d.length>1?(f+h)%d.length:0;rW.current[e]=y,s.push(...function(e,t,r){if(0===e.length||r<=0)return[];let n=[];for(let a=0;a{_(!0),O("");try{if(t8.current){I(null),J(!1),O("");return}let e=j||k;if(!e){I(null),J(!1),O("Reading is not connected yet. Please try again after the dataset API is available.");return}let t=!j&&!!k,r=[];try{r=await eR()}catch{r=[]}let n=async r=>fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({currentReverseTime:Y(new Date),excludeDataSets:r,...t?{triggerGenerate:!1}:{}})}),a=await n(r);if(!a.ok){if(404===a.status){t9.current+=1,t9.current>=3&&(t8.current=!0),O(""),I(null),J(!1);return}throw Error(`Reading request failed with status ${a.status}`)}let i=await a.json(),s="object"==typeof i&&null!==i?i:null;if(null!==s&&"meta"in s&&"object"==typeof s.meta&&s.meta?.allExcluded===!0)try{if(await eT(),r=[],!(a=await n([])).ok)throw Error(`Reading request failed with status ${a.status}`);i=await a.json(),O("")}catch{O("All reading datasets were completed, but history reset failed. Please try again.")}let o=Z("object"==typeof i&&null!==i&&"passageData"in i?i.passageData:i);if(!o)throw Error("Invalid reading payload shape");if(!o.dataSetHash)throw Error("Missing dataSetHash in reading payload");let l=o;if(e$(l,r)){let e=[...r];for(let t=0;t<3&&l.dataSetHash;t+=1){e.push({dataSetHash:l.dataSetHash});let t=await n(e);if(!t.ok)break;let a=await t.json(),i=Z("object"==typeof a&&null!==a&&"passageData"in a?a.passageData:a);if(!i||(l=i,!e$(l,r)))break}}t9.current=0,t8.current=!1,I(l),J(!1)}catch{I(null),J(!1),O("We couldn't load a reading dataset right now. Please tap the Reading title or Refresh Passage again.")}finally{_(!1)}},rY=async()=>{if(S)try{0===t6.current.length&&(t6.current=function(){let e=[...W];for(let t=e.length-1;t>0;t-=1){let r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}());let e=t6.current.pop()||W[Math.floor(Math.random()*W.length)];await fetch(S,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({field:e})})}catch{}},rZ=()=>{let e=Date.now(),t=t4.current.filter(t=>e-t<=5e3);t.push(e);let r=t.length>=10;t4.current=r?[]:t,r&&!B&&rY()},rQ=()=>{B||rG()},rX=()=>{if(L){if(V)return void J(!1);J(!0),eD(L)}},r0=async()=>{ey(!0),ef("");try{var e,t;let r;if(rr.current){ep(null),ef("");return}if(!A){ep(null),ef("Writing prompts are not available right now.");return}let n=[];try{n=await eH()}catch{n=[]}let a=async e=>{try{return await fetch(A,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({currentReverseTime:Y(new Date),excludeDataSets:e})})}catch{return null}},i=await a((e=n,t=rn.current,r=new Set,e.forEach(e=>{if("string"!=typeof e?.dataSetHash)return;let t=ew(e.dataSetHash);t&&r.add(t)}),t.forEach(e=>{let t=ew(e);t&&r.add(t)}),Array.from(r).map(e=>({dataSetHash:e}))));if(!i){ep(null),e4(null),ef("We couldn't load a writing prompt right now. Please tap the Writing title or Refresh again.");return}if(!i.ok){if(404===i.status){rt.current+=1,rt.current>=3&&(rr.current=!0),ep(null),ef("");return}throw Error(`Writing request failed with status ${i.status}`)}let s=await i.json();if("object"==typeof s&&null!==s&&"meta"in s&&"object"==typeof s.meta&&s.meta?.noData===!0){ep(null),e4(null),ef("We couldn't load a writing prompt right now.");return}let o="object"==typeof s&&null!==s?s:null;if(null!==o&&"meta"in o&&"object"==typeof o.meta&&o.meta?.allExcluded===!0)try{if(await eM(),n=[],rn.current=[],!(i=await a([])))throw Error("Writing request failed");if(!i.ok)throw Error(`Writing request failed with status ${i.status}`);s=await i.json(),ef("")}catch{ef("All writing prompts were completed, but history reset failed. Please try again.")}let l=X("object"==typeof s&&null!==s&&"taskData"in s?s.taskData:"object"==typeof s&&null!==s&&"passageData"in s?s.passageData:s);if(!l)throw Error("Invalid writing payload shape");if(!l.dataSetHash)throw Error("Missing dataSetHash in writing payload");let c=l;if(eP(c,n)){let e=[...n];for(let t=0;t<3&&c.dataSetHash;t+=1){e.push({dataSetHash:c.dataSetHash});let t=await a(e);if(!t||!t.ok)break;let r=await t.json(),i=X("object"==typeof r&&null!==r&&"taskData"in r?r.taskData:"object"==typeof r&&null!==r&&"passageData"in r?r.passageData:r);if(!i||(c=i,!eP(c,n)))break}}if(rt.current=0,rr.current=!1,c.dataSetHash){let e=ew(c.dataSetHash),t=[e,...rn.current.filter(t=>t!==e)];rn.current=t.slice(0,12)}let d="",u=null;if(c.dataSetHash)try{let e=await eE(c.dataSetHash);e&&(d=e.answer,u=e.score)}catch{d="",u=null}ep(c),ev(d),e4(u),e7(!1)}catch{ep(null),e4(null),ef("We couldn't load a writing prompt right now. Please tap the Writing title or Refresh again.")}finally{ey(!1)}},r1=()=>{let e=Date.now(),t=t7.current.filter(t=>e-t<=5e3);t.push(e);let r=t.length>=10;t7.current=r?[]:t,r&&!eh&&(()=>{if(N&&!re.current){try{new URL(N)}catch{return}re.current=!0,fetch(N,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({taskType:"Task2",asyncTrigger:!0})}).then(()=>{}).catch(()=>{}).finally(()=>{re.current=!1})}})()},r2=()=>{eh||r0()},r3=async()=>{let e;if(!G)return;eC(G);let t=eb.trim(),r=en(t);if(r<250||r>320){ef("Your answer must be between 250 and 320 words before scoring."),e4(null);return}if((e=t.trim())&&([/```|~~~/i,/<\/?[a-z][^>]*>/i,/\b(ignore\s+previous\s+instructions|system\s+prompt|developer\s+message|jailbreak|prompt\s*injection)\b/i,/\b(select\s+\*|union\s+select|drop\s+table|insert\s+into|delete\s+from|alter\s+table|information_schema)\b/i,/\b(rm\s+-rf|curl\s+https?:\/\/|wget\s+https?:\/\/|powershell\s+-|cmd\s+\/c|bash\s+-c)\b/i,/\b(eval\(|new\s+Function\(|document\.cookie|localStorage\.|sessionStorage\.|window\.|process\.env)\b/i,/\b(api[_-]?key|access[_-]?token|secret[_-]?key|authorization:\s*bearer)\b/i].some(t=>t.test(e))||(e.match(/[{}<>\[\]`$\\|;]/g)||[]).length/e.length>.045||(e.match(/https?:\/\/|www\./gi)||[]).length>=2)){ef("Your answer contains unsupported code-like or unsafe patterns. Please submit a normal IELTS essay response."),e4(null);return}if(nT)return void ef(`Please wait ${nD} more second(s) before scoring again.`);if(!$){ef("Scoring is not available right now."),e4(null);return}ek(!0),ef("");let n=Date.now()+1e4;ej(n),e9(n);let a=JSON.stringify({prompt:G.topic,answer:t,rubricReference:"https://ielts.org/take-a-test/test-types/ielts-academic-test/ielts-academic-format-writing"});try{let e;try{e=await fetch($,{method:"POST",headers:eN(),body:a})}catch(r){let t=r instanceof Error?r.message.trim():"";if(!/failed to fetch|networkerror|load failed/i.test(t))throw r;e=await fetch($,{method:"POST",headers:{"Content-Type":"application/json"},body:a})}if(!e.ok){if(429===e.status){let t=await e.json(),r="number"==typeof t.retryAfterMs&&Number.isFinite(t.retryAfterMs)?Math.max(0,t.retryAfterMs):1e4,n=Date.now()+r;ej(n),e9(n),ef("string"==typeof t.message&&t.message.trim().length>0?t.message:"Scoring is temporarily rate-limited. Please wait and try again."),e4(null);return}let t="";try{let r=await e.json();"string"==typeof r.message&&(t=r.message.trim())}catch{}ef(t.length>0?t:`Writing score request failed with status ${e.status}.`),e4(null);return}let r=await e.json(),n=ee("object"==typeof r&&null!==r&&"scoreResult"in r?r.scoreResult:"object"==typeof r&&null!==r&&"result"in r?r.result:"object"==typeof r&&null!==r&&"grading"in r?r.grading:r);if(!n)throw Error("Invalid writing score payload shape");e4(n),G.dataSetHash&&await eL(G.dataSetHash,{answer:t,score:n})}catch(t){let e=t instanceof Error?t.message.trim():"";/failed to fetch|networkerror|load failed/i.test(e)?ef("Writing score request was blocked before reaching the API (network/CORS). Refresh and try again. If it persists, check writing score endpoint CORS settings."):ef(e.length>0?`We couldn't score your writing answer right now. ${e}`:"We couldn't score your writing answer right now."),e4(null)}finally{ek(!1)}},r5=async()=>{ti(!0),tn("");try{if(rs.current){tt(null),to(!1),tn("");return}if(!D){tt(null),to(!1),tn("Listening is not connected yet. Please try again after the dataset API is available.");return}let e=[];try{e=await eq()}catch{e=[]}let t=async e=>fetch(D,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({currentReverseTime:Y(new Date),excludeDataSets:e})}),r=await t(e);if(!r.ok){if(404===r.status){ri.current+=1,ri.current>=3&&(rs.current=!0),tt(null),to(!1),tn("");return}throw Error(`Listening request failed with status ${r.status}`)}let n=await r.json(),a="object"==typeof n&&null!==n?n:null;if(null!==a&&"meta"in a&&"object"==typeof a.meta&&a.meta?.allExcluded===!0)try{if(await eF(),e=[],!(r=await t([])).ok)throw Error(`Listening request failed with status ${r.status}`);n=await r.json(),tn("")}catch{tn("All listening datasets were completed, but history reset failed. Please try again.")}let i=Q("object"==typeof n&&null!==n&&"passageData"in n?n.passageData:n);if(!i)throw Error("Invalid listening payload shape");if(!i.dataSetHash)throw Error("Missing dataSetHash in listening payload");let s=i;if(eI(s,e)){let r=[...e];for(let n=0;n<3&&s.dataSetHash;n+=1){r.push({dataSetHash:s.dataSetHash});let n=await t(r);if(!n.ok)break;let a=await n.json(),i=Q("object"==typeof a&&null!==a&&"passageData"in a?a.passageData:a);if(!i||(s=i,!eI(s,e)))break}}ri.current=0,rs.current=!1,tt(s),to(!1)}catch{tt(null),to(!1),tn("We couldn't load a listening dataset right now. Please tap the Listening title or Refresh Listening again.")}finally{ti(!1)}},r4=async()=>{if(R)try{await fetch(R,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}},r6=()=>{let e=Date.now(),t=ra.current.filter(t=>e-t<=5e3);t.push(e);let r=t.length>=10;ra.current=r?[]:t,r&&!ta&&r4()},r9=()=>{ta||(ea(),tc(!1),r5())},r8=()=>{if(te){if(ts)return void to(!1);to(!0),eO(te)}},r7=async()=>{if(!te)return;if(!("speechSynthesis"in window)||"u"{tc(!1)},t.onerror=()=>{tc(!1)},window.speechSynthesis.speak(t)},ne=()=>{ea(),tb(!1),tv(!1),tu(!1)},nt=async e=>{let t=e?.restoreSession??!0;ty(!0),tf("");try{if(rc.current){tp(null),tf("");return}if(!P){tp(null),tf("Speaking prompts are not available right now.");return}let e=[];try{e=await eU()}catch{e=[]}let r=async e=>fetch(P,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({currentReverseTime:Y(new Date),excludeDataSets:e})}),n=await r(e);if(!n.ok)throw Error(`Speaking request failed with status ${n.status}`);let a=await n.json();if("object"==typeof a&&null!==a&&"meta"in a&&"object"==typeof a.meta&&a.meta?.noData===!0){rl.current+=1,rl.current>=3&&(rc.current=!0),tp(null),tf("No speaking prompt is currently available from the configured dataset.");return}if("object"==typeof a&&null!==a&&"meta"in a&&"object"==typeof a.meta&&a.meta?.allExcluded===!0)try{if(await eW(),e=[],!(n=await r([])).ok)throw Error(`Speaking request failed with status ${n.status}`);a=await n.json()}catch{tf("All speaking prompts were completed, but history reset failed. Please try again.")}let i=et("object"==typeof a&&null!==a&&"taskData"in a?a.taskData:a);if(!i||!i.dataSetHash)throw Error("Invalid speaking payload shape");let s=i;if(ez(s,e)){let t=[...e];for(let n=0;n<3&&s.dataSetHash;n+=1){t.push({dataSetHash:s.dataSetHash});let n=await r(t);if(!n.ok)break;let a=await n.json(),i=et("object"==typeof a&&null!==a&&"taskData"in a?a.taskData:a);if(!i||(s=i,!ez(s,e)))break}}if(rl.current=0,rc.current=!1,tp(s),tN("idle"),t$(0),rv.current=0,tD(0),tP(""),tC(0),rU(""),tV(null),ne(),t&&s.dataSetHash)try{let e=await eB(s.dataSetHash);e&&(tP(e.audioDataUrl),tE(e.audioMimeType||"audio/webm"),tC(e.audioDurationSec||0),rv.current=e.audioDurationSec||0,rU(e.transcript||""),tV(e.score),tN("recorded"))}catch{}}catch{tp(null),tf("We couldn't load a speaking prompt right now. Please tap the Speaking title or Refresh again.")}finally{ty(!1)}},nr=async()=>{if(!T)return tf("Speaking create endpoint is not configured. Set NEXT_PUBLIC_SPEAKING_CREATE_ENDPOINT."),!1;try{if(!(await fetch(T,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})})).ok)return!1;return!0}catch{return tf("Speaking generation request failed. Please check your network and endpoint settings."),!1}},nn=()=>{let e=Date.now(),t=ro.current.filter(t=>e-t<=5e3);t.push(e);let r=t.length>=10;ro.current=r?[]:t,r&&!th&&(async()=>{await nr()&&(await nt(),window.setTimeout(()=>{nt({restoreSession:!1})},6e3))})()},na=()=>{th||(ne(),nt({restoreSession:!1}))},ni=async(e,t)=>{if(!e)return;if(!("speechSynthesis"in window)||"u"{tb(!1),tv(!1)},r.onerror=()=>{tb(!1),tv(!1)},window.speechSynthesis.speak(r)},ns=()=>{rq.current&&(clearInterval(rq.current),rq.current=null)},no=()=>{if(rk.current&&(clearTimeout(rk.current),rk.current=null),rN.current&&(clearTimeout(rN.current),rN.current=null),ns(),rR.current=0,rD.current+=1,rC.current=0,rM.current=0,rL.current=!1,rI.current=0,rA.current.trim().length>0&&(0===rS.current.trim().length||rS.current.trim().length{rj.current=!1,ns(),rp.current&&(clearInterval(rp.current),rp.current=null),rd.current&&"inactive"!==rd.current.state&&rd.current.stop(),ru.current&&(ru.current.getTracks().forEach(e=>{e.stop()}),ru.current=null),((e=250)=>{rk.current&&(clearTimeout(rk.current),rk.current=null),rk.current=setTimeout(()=>{rk.current=null,no()},Math.max(0,e))})(250),null!==rh.current&&(cancelAnimationFrame(rh.current),rh.current=null),rf.current=null,rg.current&&(rg.current.close(),rg.current=null),tD(0)};rw.current=nt,rb.current=nl;let nc=()=>{rk.current&&(clearTimeout(rk.current),rk.current=null),no();let e=window.SpeechRecognition||window.webkitSpeechRecognition;if(!e)return tf("Speech recognition is not available in this browser. Speaking scoring requires transcript capture. Use the latest Chrome or Edge on HTTPS and allow microphone access."),!1;try{rA.current=rS.current.trim(),r$.current=[],rR.current=0,rT.current=0,rP.current=0,rH.current=0,rC.current=0,rM.current=0,rL.current=!1,rI.current=0;let t=rD.current+1;rD.current=t;let r=new e;return r.lang="en-US",r.interimResults=!0,r.continuous=!0,rK("recognition.start",`session=${t}`),r.onstart=()=>{rK("recognition.onstart",`session=${t}`)},r.onaudiostart=()=>{rK("recognition.onaudiostart",`session=${t}`)},r.onaudioend=()=>{rK("recognition.onaudioend",`session=${t}`)},r.onsoundstart=()=>{rK("recognition.onsoundstart",`session=${t}`)},r.onsoundend=()=>{rK("recognition.onsoundend",`session=${t}`)},r.onspeechstart=()=>{rK("recognition.onspeechstart",`session=${t}`)},r.onspeechend=()=>{rK("recognition.onspeechend",`session=${t}`)},r.onnomatch=()=>{rK("recognition.onnomatch",`session=${t}`)},r.onresult=e=>{rR.current=0,rT.current=Date.now(),rP.current+=1,rC.current=0;let t="number"==typeof e.resultIndex&&Number.isFinite(e.resultIndex)?Math.max(0,e.resultIndex):0,r=[],n=[];for(let a=t;a0&&(rA.current=[rA.current,r.join(" ")].join(" ").replace(/\s+/g," ").trim());let a=[...r,...n].map(e=>e.trim()).filter(e=>e.length>0);if(a.length>0){let e=[...r$.current,...a].map(e=>e.replace(/\s+/g," ").trim()).filter(e=>e.length>0);r$.current=e.slice(Math.max(0,e.length-320))}let i=[rA.current,n.join(" ")].join(" ").replace(/\s+/g," ").trim();rU(i),rK("recognition.result",`final=${r.length}, interim=${n.length}, textLen=${i.length}`),tK(e=>({...e,results:e.results+1,lastResultAtMs:Date.now()}))},r.onerror=e=>{let t="string"==typeof e.error?e.error:"unknown",r="string"==typeof e.message?e.message:"";rK("recognition.error",`${t}${r?` (${r})`:""}`),"aborted"!==t&&(tK(e=>({...e,errors:e.errors+1,lastError:t,lastErrorAtMs:Date.now()})),rH.current+=1,"not-allowed"===t||"service-not-allowed"===t?tf("Speech recognition permission is blocked. Allow microphone and speech recognition in browser site settings, then record again."):"audio-capture"===t?tf("Speech recognition could not access your microphone audio stream. Check your input device and browser permission."):"network"===t?tf("Speech recognition encountered a network issue. Keep recording and try scoring again after stopping."):"no-speech"===t?tf("No speech was detected for STT. Speak a bit louder or closer to the microphone."):tf(`Speech recognition error: ${t}. Please record again.`))},r.onend=()=>{if(tK(e=>({...e,ends:e.ends+1})),!rj.current||t!==rD.current)return void rK("recognition.end",`session=${t}, ignored=true`);let e=rP.current>0,n=rH.current>0,a=!e&&!n,i=Date.now()-rE.current<12e3;if(a&&(rC.current+=1,tK(e=>({...e,silentEnds:rC.current})),rK("recognition.end",`session=${t}, silent-end=${rC.current}, recentVoice=${String(i)}`)),!a&&rR.current>=240){rK("recognition.end",`session=${t}, restart-limit-reached`),tf("Speech recognition became unstable during recording. Stop and record again.");return}let s=a?rR.current:rR.current+1,o=a?i?60:160:i?60:Math.min(1200,250*s),l=Date.now()-rM.current,c=l<80?Math.max(o,80-l):o;rR.current=s,rK("recognition.end",`session=${t}, restarting attempt=${s}, delayMs=${c}, silentEndLoop=${String(a)}`),rN.current&&(clearTimeout(rN.current),rN.current=null),rN.current=setTimeout(()=>{if(rN.current=null,rj.current&&t===rD.current)try{r.start(),rM.current=Date.now(),rL.current=!1,rK("recognition.restart",`session=${t}, attempt=${s}, started=true`),tK(e=>({...e,restarts:e.restarts+1}))}catch{rK("recognition.restart",`session=${t}, attempt=${s}, started=false`);let e=nc();rK("recognition.restart.recycle",`session=${t}, recycled=${String(e)}`)}},c)},r.start(),ry.current=r,ns(),rq.current=setInterval(()=>{if(!rj.current||!tq||!ry.current)return;let e=Date.now(),t=rT.current;if(t<=0)return;let r=e-t,n=e-rO.current;r<6e3||n<3e3||(rO.current=e,rK("recognition.watchdog",`staleForMs=${r}, action=restart`),tK(e=>({...e,watchdogRestarts:e.watchdogRestarts+1})),no(),nc()||rK("recognition.watchdog","restart-failed"))},1500),!0}catch{return rK("recognition.start","failed to initialize recognizer"),tf("Speech recognition could not start on this device. Speaking scoring requires transcript capture. Check browser permissions, then try again."),!1}},nd=async e=>{try{let t=new AudioContext,r=t.createAnalyser();r.fftSize=1024,t.createMediaStreamSource(e).connect(r),rg.current=t,rf.current=r;let n=new Uint8Array(r.fftSize),a=()=>{if(!rf.current)return;rf.current.getByteTimeDomainData(n);let e=0;for(let t=0;t=.015&&(rE.current=Date.now(),rL.current&&rj.current&&tq&&!ry.current&&(rL.current=!1,rK("recognition.resume","voice-activity-detected"),nc())),tD(Math.min(100,Math.round(260*t))),rh.current=requestAnimationFrame(a)};rh.current=requestAnimationFrame(a)}catch{}},nu=async()=>{if(!tm||th)return;if("recording"===tk){rK("recording.toggle","action=complete"),nl(),tN("recorded");return}if(rK("recording.toggle",`action=start, liveSttEnabled=${String(tq)}`),"u""audioinput"===e.kind))return void tf("No audio input device is detected. Connect/enable a microphone and try again.")}catch{}ne(),rx.current&&(rx.current.pause(),rx.current=null),tB(!1),tf(""),tV(null),tJ(""),rU(""),rA.current="",r$.current=[],rF.current=tq,tP(""),tC(0),rv.current=0,rE.current=0,rL.current=!1,t$(0),tD(0);try{let e=await navigator.mediaDevices.getUserMedia({audio:!0});ru.current=e,rK("recording.stream",`tracks=${e.getAudioTracks().length}`),e.getAudioTracks().forEach((e,t)=>{rK("recording.track",`index=${t}, label=${e.label||"unknown"}`),e.onended=()=>{rK("recording.track.ended",`index=${t}`)},e.onmute=()=>{rK("recording.track.mute",`index=${t}`)},e.onunmute=()=>{rK("recording.track.unmute",`index=${t}`)}});let t=new MediaRecorder(e);rd.current=t,rm.current=[],rK("recording.mediaRecorder",`mimeType=${t.mimeType||"unknown"}`),t.onerror=()=>{rK("recording.mediaRecorder.error","onerror")},t.ondataavailable=e=>{e.data.size>0&&(rm.current.push(e.data),rK("recording.chunk",`size=${e.data.size}`))},t.onstop=()=>{rK("recording.stop",`chunks=${rm.current.length}`);let e=new Blob(rm.current,{type:t.mimeType||"audio/webm"}),r=new FileReader;r.onloadend=()=>{let e="string"==typeof r.result?r.result:"",n=rv.current;tP(e),tE(t.mimeType||"audio/webm"),tC(n),tm?.dataSetHash&&e&&e_(tm.dataSetHash,{audioDataUrl:e,audioMimeType:t.mimeType||"audio/webm",audioDurationSec:n,transcript:rS.current,score:null})},r.readAsDataURL(e),tN("recorded")},t.start(250),rj.current=!0,tN("recording"),rp.current=setInterval(()=>{t$(e=>{let t=e+1;return(rv.current=t,t>=120)?(nl(),120):t})},1e3),nc()||tf("Recording started, but STT could not start on this browser session. Please record again."),await nd(e)}catch(r){let e="object"==typeof r&&null!==r&&"name"in r?String(r.name):"",t=e.trim().length>0?` (browser code: ${e})`:"";"NotAllowedError"===e||"PermissionDeniedError"===e?tf(`Microphone permission was denied. Allow microphone access in your browser site settings and try again.${t}`):"NotFoundError"===e||"DevicesNotFoundError"===e?tf(`No microphone device was found. Connect a microphone and try again.${t}`):"NotReadableError"===e||"TrackStartError"===e?tf(`Microphone is busy or unavailable. Close other apps using the microphone and try again.${t}`):"SecurityError"===e?tf(`Microphone access is blocked by browser security settings.${t}`):tf(`Could not start microphone recording on this device. Check browser permission and input device settings.${t}`),nl(),tN("idle")}},nm=()=>{if(tT)try{if(rx.current){rx.current.pause(),rx.current=null,tB(!1);return}let e=new Audio(tT);e.onplay=()=>tB(!0),e.onended=()=>{tB(!1),rx.current=null},e.onpause=()=>{tB(!1),rx.current===e&&(rx.current=null)},e.onerror=()=>{tB(!1),rx.current===e&&(rx.current=null)},rx.current=e,e.play()}catch{tf("Could not play your recording in this browser."),tB(!1)}},np=Math.max(0,tS-Date.now()),ng=Math.ceil(np/1e3),nf=np>0,nh=async()=>{if(!tm||!tm.dataSetHash)return;if(!tT)return void tf("Please record your answer first.");let e=tH>0?tH:rv.current;if(e<30||e>120)return void tf("Recording length must be between 30 and 120 seconds before scoring.");let t=rS.current.trim().length>0?rS.current.trim():tL.trim();ex(t)&&(no(),t=rS.current.trim().length>0?rS.current.trim():rA.current.trim());let r=ex(t),n=t;if(r){let t=r$.current.join(" ").replace(/\s+/g," ").trim();n=t.length>0?t:`Automatic STT transcript was unavailable for this speaking attempt. The candidate delivered a spoken response for approximately ${e} seconds. Score this as a low-confidence transcript case and focus feedback on overall speaking performance signals.`,tf(t.length>0?"STT was partial, so scoring will proceed with captured STT fragments.":"STT transcript was empty, but scoring will proceed using an automatic fallback transcript.")}let a=[tm.topicField?`Topic field: ${tm.topicField}`:"","Cue card:",tm.topic].filter(e=>e.length>0).join("\n").trim();if(nf)return void tf(`Please wait ${ng} more second(s) before scoring again.`);if(!H)return void tf("Speaking scoring is not available right now.");t_(!0),tf(""),tJ(n);let i=Date.now()+1e4;eA(i),tj(i);let s=JSON.stringify({prompt:a,transcript:n,durationSeconds:e,rubricReference:"https://ielts.org/take-a-test/test-types/ielts-academic-test/ielts-academic-format-speaking"});try{let t;try{t=await fetch(H,{method:"POST",headers:eN(),body:s})}catch(r){let e=r instanceof Error?r.message.trim():"";if(!/failed to fetch|networkerror|load failed/i.test(e))throw r;t=await fetch(H,{method:"POST",headers:{"Content-Type":"application/json"},body:s})}if(!t.ok){if(429===t.status){let e=await t.json(),r="number"==typeof e.retryAfterMs&&Number.isFinite(e.retryAfterMs)?Math.max(0,e.retryAfterMs):1e4,n=Date.now()+r;eA(n),tj(n),tf("string"==typeof e.message&&e.message.trim().length>0?e.message:"Speaking scoring is temporarily rate-limited. Please wait and try again.");return}let e="";try{let r=await t.json();"string"==typeof r.message&&(e=r.message.trim())}catch{}tf(e.length>0?e:`Speaking scoring request failed with status ${t.status}.`),tV(null);return}let r=await t.json(),a=er("object"==typeof r&&null!==r&&"scoreResult"in r?r.scoreResult:r);if(!a)throw Error("Invalid speaking score payload shape");tV(a),await eK(tm),await e_(tm.dataSetHash,{audioDataUrl:tT,audioMimeType:tM,audioDurationSec:e,transcript:n,score:a})}catch(t){let e=t instanceof Error?t.message.trim():"";/failed to fetch|networkerror|load failed/i.test(e)?tf("Speaking score request was blocked before reaching the API (network/CORS). Please refresh and try again. If it still fails, verify the score endpoint CORS allows POST from this origin."):tf(e.length>0?`We couldn't score your speaking answer right now. ${e}`:"We couldn't score your speaking answer right now."),tV(null)}finally{t_(!1)}};(0,a.useRef)(nh).current=nh;let ny=async()=>{p(!0),C("");try{let e=await e3();i(e),o(t=>rJ(e,t,!1));let t=new Set(e.map(e=>e.yymmdd));Object.keys(rW.current).forEach(e=>{t.has(e)||delete rW.current[e]}),Object.keys(rB.current).forEach(e=>{t.has(e)||delete rB.current[e]});let r=e.reduce((e,t)=>("string"==typeof t.meaning&&t.meaning.trim().length>0&&(e[t.voca]=t.meaning.trim()),e),{});c(e=>({...r,...e}))}catch{C("Could not load your saved vocabulary list.")}finally{p(!1)}};rz.current=ny;let nw=(0,a.useCallback)(async(e,t)=>{let r=e.filter(e=>{let t=l[e.voca];return!t||!ec(t)});if(0===r.length)return;let n={};await Promise.all(r.map(async e=>{try{let r=await eo(e.voca,t);if(r){n[e.voca]=r;try{await e0(e,r)}catch{}}}catch{}})),Object.keys(n).length>0&&c(e=>({...e,...n}))},[l]),nb=async e=>{ea(),tc(!1);let t=el(e);if(d[t])return void u(e=>{let r={...e};return delete r[t],r});let r=l[e.voca]??null;if(!r||!ec(r)){try{let t=await eo(e.voca,M);t&&(r=t)}catch{}if(r){let t=r;c(r=>({...r,[e.voca]:t}))}}if(!r)return void C("Meaning is not available right now. Please try again.");u(e=>({...e,[t]:!0}));try{await eX(e,r);let t={...e,yymmdd:em(new Date),createdAt:Date.now(),meaning:r};i(r=>r.map(r=>r.id===e.id?t:r))}catch{}},nx=async()=>{u({});try{let e=await e3();if(0===e.length||0===r.length){await e5(),await rz.current();return}}catch{C("Could not refresh your vocabulary list right now.");return}o(e=>rJ(r,e,!0))},nv=()=>{t1.current&&(clearTimeout(t1.current),t1.current=null)},nS=()=>{t2.current&&(clearTimeout(t2.current),t2.current=null)},nj=()=>{t3.current+=1,nS(),ea(),tu(!1)},nk=async e=>{if(window.confirm(`Delete "${e.voca}" from your vocabulary list?`))try{if(!await e1(e))return void C("Could not find the selected word in local storage.");u(t=>{let r={...t};return delete r[el(e)],r}),await ny(),C(`Deleted "${e.voca}" from local storage.`)}catch{C("Could not delete the selected word right now.")}},nN=()=>{nv()};(0,a.useEffect)(()=>{(async()=>{let e,t;E("u"{if(e6<=Date.now())return;let e=window.setInterval(()=>{Date.now()>=e6&&e9(0)},400);return()=>{window.clearInterval(e)}},[e6]),(0,a.useEffect)(()=>{if(tS<=Date.now())return;let e=window.setInterval(()=>{Date.now()>=tS&&tj(0)},400);return()=>{window.clearInterval(e)}},[tS]),(0,a.useEffect)(()=>()=>{t1.current&&(clearTimeout(t1.current),t1.current=null),t2.current&&(clearTimeout(t2.current),t2.current=null),ea(),tc(!1),rb.current(),ne(),rx.current&&(rx.current.pause(),rx.current=null)},[]),(0,a.useEffect)(()=>{let e=navigator.wakeLock;if(!e?.request)return;let t=!0,r=async()=>{let e=t0.current;if(!e||e.released){t0.current=null;return}try{await e.release()}catch{}finally{t0.current===e&&(t0.current=null)}},n=async()=>{if(t&&"visible"===document.visibilityState&&(!t0.current||t0.current.released))try{let r=await e.request("screen");if(!t)return void await r.release();t0.current=r}catch{}},a=()=>{"visible"===document.visibilityState?n():r()},i=()=>{n()};return document.addEventListener("visibilitychange",a),window.addEventListener("focus",i),window.addEventListener("pointerdown",i),window.addEventListener("keydown",i),n(),()=>{t=!1,document.removeEventListener("visibilitychange",a),window.removeEventListener("focus",i),window.removeEventListener("pointerdown",i),window.removeEventListener("keydown",i),rk.current&&(clearTimeout(rk.current),rk.current=null),r()}},[]),(0,a.useEffect)(()=>{let e=()=>{let e=tQ.current?.getBoundingClientRect().height??64;Number.isFinite(e)&&!(e<=0)&&tZ(e)};e();let t=tQ.current,r=null;return"u">typeof ResizeObserver&&t&&(r=new ResizeObserver(()=>{e()})).observe(t),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),r?.disconnect()}},[]),(0,a.useEffect)(()=>{nw(s,M)},[s,M,nw]),(0,a.useEffect)(()=>{rV()},[rV,eb,G?.dataSetHash]);let nA=en(eb),n$=nA>=250&&nA<=320,nR=Math.max(0,e6-Date.now()),nD=Math.ceil(nR/1e3),nT=nR>0,nP=tl||tw||tx||td,nH=!te||ta||!tl&&nP,nC=!tm||th||!tw&&nP,nM=!tm?.modelAnswer||th||!tx&&nP,nE=async r=>{r.preventDefault();let n=es(e);if(n){if(t(""),!x)return void C("Save service is currently unavailable.");if(n.length>40)return void C("Vocabulary must be 40 characters or less.");try{if(!await eQ())return void C("Please wait at least 1 second before saving another word.")}catch{C("Could not check local save interval right now.");return}w(!0),C("");try{let e=await fetch(x,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({voca:n})});if(400===e.status)return void C("Vocabulary must be 40 characters or less.");if(429===e.status)return void C("Please wait at least 1 second before saving another word.");if(!e.ok&&409!==e.status)throw Error(`Failed to save vocabulary (${e.status}).`);if(!await eY(n)&&!await eZ(n))return void C("Please wait at least 1 second before saving another word.");C("Saved successfully."),await ny()}catch(e){if(e instanceof Error&&"LOCAL_SAVE_INTERVAL_LIMIT"===e.message)return void C("Please wait at least 1 second before saving another word.");C("Could not save vocabulary right now. Please try again in a moment.")}finally{w(!1)}}};return(0,n.jsxs)("div",{className:"mx-auto flex min-h-screen w-full max-w-5xl flex-col px-6 pt-0 pb-28",children:[(0,n.jsx)("div",{ref:tQ,className:"fixed inset-x-0 top-0 z-30 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/85",children:(0,n.jsxs)("div",{className:"mx-auto flex w-full max-w-5xl flex-nowrap items-center gap-3 overflow-hidden px-6 py-2",children:[(0,n.jsx)("div",{"aria-label":"ForMeLog symbol",className:"shrink-0 rounded-xl px-3 py-1.5 font-extrabold leading-none",style:{backgroundColor:"rgb(90, 90, 90)",color:"rgb(217, 217, 217)"},children:(0,n.jsxs)("span",{className:`whitespace-nowrap ${K}`,children:[(0,n.jsx)("span",{className:"align-baseline text-[0.7em]",children:"for"})," ",(0,n.jsx)("span",{className:"align-baseline text-[0.85em]",children:"me"})," ",(0,n.jsx)("span",{className:"align-baseline text-[1em]",children:"Log"})]})}),(0,n.jsx)("h1",{className:`whitespace-nowrap ${K} font-bold tracking-tight`,children:"IELTS.ForMeLog"})]})}),(0,n.jsxs)("main",{className:"flex flex-1 flex-col gap-8",style:{paddingTop:`${tY}px`},children:[(0,n.jsxs)("section",{id:"section-voca",className:"mt-3 scroll-mt-24 rounded-xl border bg-card p-5",children:[(0,n.jsx)("h2",{className:"text-xl font-semibold text-foreground",children:"Vocabulary"}),(0,n.jsx)("p",{className:"mt-2 text-sm text-muted-foreground",children:"Build your own personalized vocabulary notebook and review words over time."}),(0,n.jsxs)("form",{className:"mt-4 grid grid-cols-[minmax(0,7fr)_minmax(0,3fr)] items-center gap-3",onSubmit:nE,children:[(0,n.jsx)("label",{className:"sr-only",htmlFor:"voca-input",children:"Vocabulary input"}),(0,n.jsx)("input",{id:"voca-input",value:e,onChange:e=>t(e.target.value),placeholder:"Enter a vocabulary word",maxLength:40,className:"box-border h-[2.625rem] min-w-0 flex-1 rounded-md border border-input bg-background px-3 py-0 text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring",style:{height:"42px"},disabled:g}),(0,n.jsx)("button",{id:"voca-add-button",type:"submit",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",style:{height:"42px"},disabled:!tG||g||0===e.trim().length,children:g?"Saving...":"Add"})]}),v&&(0,n.jsx)("p",{className:"mt-3 text-sm text-muted-foreground",children:v}),(0,n.jsxs)("div",{className:"mt-4 rounded-md border bg-background p-3",children:[(0,n.jsx)("div",{className:"flex items-center justify-between gap-3",children:(0,n.jsxs)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:nx,disabled:m,"aria-label":"Refresh vocabulary list",title:"Refresh list",children:[(0,n.jsxs)("svg",{viewBox:"0 0 24 24",className:"h-3.5 w-3.5","aria-hidden":"true",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[(0,n.jsx)("path",{d:"M21 12a9 9 0 1 1-2.64-6.36"}),(0,n.jsx)("path",{d:"M21 3v6h-6"})]}),"Refresh"]})}),(0,n.jsx)("div",{className:"mt-3",children:m?(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:"Loading..."}):0===s.length?(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:"No words saved yet."}):(0,n.jsx)("ul",{className:"grid gap-2",children:s.map(e=>{let t,r;return(0,n.jsx)("li",{className:"text-sm font-medium",children:(r=(t=!!d[el(e)])&&l[e.voca]?ed(l[e.voca]):[],(0,n.jsx)("button",{type:"button",onClick:()=>{if(t5.current){t5.current=!1;return}nj(),nb(e)},onPointerDown:()=>{nj(),tc(!1),nv(),t5.current=!1,t1.current=setTimeout(()=>{if(t5.current=!0,t){let t=l[e.voca]||e.meaning||"";((e,t)=>{if(tl||tw||tx)return C("Another audio is currently playing. Stop it before starting vocabulary speech.");let r=function(e,t){let r=ed(e),n=[];for(let e of r){e.label&&n.push({text:e.label,lang:ei(e.label,t),pauseAfterMs:140});let r=e.value.split(/[\/,;]+/).map(e=>e.trim()).filter(e=>e.length>0);if(r.length>0)for(let e of r)n.push({text:e,lang:ei(e,t),pauseAfterMs:140})}return n}(t,M);0===r.length?C("Meaning text is not available to read aloud."):(e=>{if(!("speechSynthesis"in window)||"u"{if(t3.current!==t)return;if(n>=e.length)return void tu(!1);let a=e[n],i=new SpeechSynthesisUtterance(a.text);i.lang=a.lang,i.rate=1.1,i.onend=()=>{if(t3.current===t){if(n>=e.length-1)return void tu(!1);nS(),t2.current=setTimeout(()=>{t2.current=null,r(n+1)},Math.max(0,a.pauseAfterMs))}},i.onerror=()=>{if(t3.current===t){if(n>=e.length-1)return void tu(!1);nS(),t2.current=setTimeout(()=>{t2.current=null,r(n+1)},80)}},window.speechSynthesis.speak(i)};r(0)})([{text:e.voca,lang:ei(e.voca,M),pauseAfterMs:1e3},...r])})(e,t);return}nk(e)},700)},onPointerUp:nN,onPointerLeave:nN,onPointerCancel:nN,onContextMenu:e=>{e.preventDefault()},onDragStart:e=>{e.preventDefault()},className:"w-full rounded-md border px-3 py-2 text-center text-sm font-semibold leading-6 active:bg-accent active:text-accent-foreground min-h-[42px]",style:{userSelect:"none",WebkitUserSelect:"none"},title:t?"Click to hide meaning. Press and hold to read this card aloud.":"Click to show meaning. Press and hold to delete.",children:t?(0,n.jsx)("span",{className:"block space-y-1 text-center text-muted-foreground",children:r.map((t,r)=>(0,n.jsxs)("span",{className:"block",children:[t.label?(0,n.jsxs)("span",{className:"font-extrabold text-foreground",children:[t.label,": "]}):null,(0,n.jsx)("span",{children:t.value})]},`${e.voca}-meaning-line-${r}`))}):(0,n.jsx)("span",{className:"text-base font-semibold text-foreground",children:e.voca})}))},el(e))})})})]})]}),(0,n.jsx)("section",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-2",children:r_.map(e=>(0,n.jsxs)("article",{id:`section-${e.key}`,className:"scroll-mt-24 rounded-xl border bg-card p-5",children:["reading"===e.key?(0,n.jsx)("button",{type:"button",onClick:rZ,className:"inline-flex items-center gap-2 text-left text-xl font-semibold text-foreground",children:(0,n.jsx)("span",{children:e.label})}):"writing"===e.key?(0,n.jsx)("button",{type:"button",onClick:r1,className:"inline-flex items-center gap-2 text-left text-xl font-semibold text-foreground",children:(0,n.jsx)("span",{children:e.label})}):"listening"===e.key?(0,n.jsx)("button",{type:"button",onClick:r6,className:"inline-flex items-center gap-2 text-left text-xl font-semibold text-foreground",children:(0,n.jsx)("span",{children:e.label})}):"speaking"===e.key?(0,n.jsx)("button",{type:"button",onClick:nn,className:"inline-flex items-center gap-2 text-left text-xl font-semibold text-foreground",children:(0,n.jsx)("span",{children:e.label})}):(0,n.jsx)("h2",{className:"text-xl font-semibold text-foreground",children:e.label}),"reading"===e.key?(0,n.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,n.jsx)("div",{className:"flex flex-wrap items-center gap-2",children:(0,n.jsxs)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground",onClick:rQ,children:[(0,n.jsx)(f,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Refresh"})]})}),q&&(0,n.jsx)("p",{className:"text-xs text-muted-foreground",children:q}),L?(0,n.jsxs)("div",{className:"space-y-4 bg-background",children:[(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsxs)("div",{className:"mb-2 flex items-center justify-between gap-2",children:[(0,n.jsx)("p",{className:"text-sm font-semibold text-foreground",children:"Passage"}),(0,n.jsxs)("p",{className:"text-xs text-muted-foreground",children:["Field: ",(0,n.jsx)("span",{className:"font-semibold text-foreground",children:L.field})]})]}),(0,n.jsx)("p",{className:"text-sm leading-6 text-foreground",children:L.passage})]}),(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsx)("p",{className:"mb-2 text-sm font-semibold text-foreground",children:"Questions"}),(0,n.jsx)("ol",{className:"grid gap-3 text-sm text-foreground",children:L.questions.map((e,t)=>{let r,a,i=L.answers[t];return(0,n.jsxs)("li",{children:[(0,n.jsx)("p",{children:(a=(r=e.trim()).replace(/^question\s*\d+\s*[:.)-]?\s*/i,"").replace(/^q\s*\d+\s*[:.)-]?\s*/i,"").replace(/^\d+\s*[:.)-]\s*/,"").trim(),`${t+1}. ${a||r}`)}),V&&i?(0,n.jsx)("p",{className:"mt-1 font-bold text-[#859BB2]",children:eu(i)}):null]},`${L.id}-q-${t}`)})})]})]}):(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:"No reading passage loaded yet."}),(0,n.jsx)("div",{className:"flex justify-end",children:(0,n.jsx)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:rX,disabled:!L,children:V?"Hide Answers":"Show Answers"})})]}):"writing"===e.key?(0,n.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,n.jsx)("div",{className:"flex flex-wrap items-center gap-2",children:(0,n.jsxs)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground",onClick:r2,children:[(0,n.jsx)(f,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Refresh"})]})}),eg&&(0,n.jsx)("p",{className:"text-xs text-muted-foreground",children:eg}),G?(0,n.jsxs)("div",{className:"space-y-4 bg-background",children:[(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsx)("p",{className:"mb-2 text-sm font-semibold text-foreground",children:G.topicField}),(0,n.jsx)("p",{className:"text-sm leading-6 text-foreground",children:G.topic})]}),(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsx)("label",{className:"mb-2 block text-sm font-semibold text-foreground",htmlFor:"writing-answer-input",children:"My Answer"}),(0,n.jsx)("textarea",{id:"writing-answer-input",ref:tX,value:eb,onChange:e=>{let t=e.target.value;ev(t),G?.dataSetHash&&eL(G.dataSetHash,{answer:t,score:eV}),eg&&ef("")},placeholder:"Write your response here.",className:"w-full resize-none overflow-hidden rounded-md border border-input bg-background px-3 py-2 text-sm leading-6 text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring"}),(0,n.jsxs)("p",{className:`mt-2 text-xs ${n$||0===nA?"text-muted-foreground":"text-[#7D665D]"}`,children:[nA," / ",320," words (minimum ",250,")"]}),(0,n.jsx)("div",{className:"mt-3 flex justify-end",children:(0,n.jsx)("button",{type:"button",className:"inline-flex box-border min-h-[2.625rem] min-w-0 items-center justify-center rounded-md bg-primary px-3 py-2 text-center font-semibold leading-tight whitespace-normal text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:r3,disabled:!G||eS||!n$||nT,children:eS?"Scoring in progress...":"Score My Answer"})})]}),eV?(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsxs)("p",{className:"text-sm font-semibold text-foreground",children:["Score: ",(0,n.jsx)("span",{className:"font-bold text-[#859BB2]",children:function(e){let t=String(e||"").trim();if(!t)return"9";if(t.includes("/"))return t;let r=t.match(/\d+(?:\.\d+)?/);if(!r)return`${t} / 9`;let n=Number.parseFloat(r[0]);if(!Number.isFinite(n))return`${t} / 9`;let a=Number.isInteger(n)?`${n}`:n.toFixed(1);return`${a} / 9`}(eV.score)})]}),(0,n.jsx)("ul",{className:"mt-2 grid gap-2 text-sm text-foreground",children:eV.comments.map((e,t)=>(0,n.jsxs)("li",{children:[t+1,". ",e]},`${G.id}-comment-${t}`))})]}):null]}):(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:"No writing prompt loaded yet."}),(0,n.jsx)("div",{className:"flex justify-end",children:(0,n.jsx)("button",{type:"button",className:"inline-flex box-border min-h-[2.625rem] min-w-0 items-center justify-center rounded-md bg-primary px-3 py-2 text-center font-semibold leading-tight whitespace-normal text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:()=>e7(e=>!e),disabled:!G?.modelAnswer,children:e8?"Hide Model Answer":"Show Model Answer"})}),G&&e8&&G.modelAnswer?(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsx)("p",{className:"mb-2 text-sm font-semibold text-foreground",children:"Model Answer"}),(0,n.jsx)("div",{className:"grid gap-3 text-sm leading-6 text-foreground",children:(function(e){let t=String(e||"").trim();if(!t)return[];let r=t.split(/\n\s*\n+/).map(e=>e.replace(/\s+/g," ").trim()).filter(Boolean);if(r.length>1)return r;let n=t.split(/(?<=[.!?])\s+/).map(e=>e.trim()).filter(Boolean);if(n.length<=4)return[t];let a=[];for(let e=0;e(0,n.jsx)("p",{children:e},`${G.id}-model-answer-${t}`))})]}):null]}):"listening"===e.key?(0,n.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsxs)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground",onClick:r9,children:[(0,n.jsx)(f,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Refresh"})]}),(0,n.jsx)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:r7,disabled:nH,children:tl?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(h,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Stop"})]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(y,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Play"})]})})]}),tr&&(0,n.jsx)("p",{className:"text-xs text-muted-foreground",children:tr}),te?(0,n.jsx)("div",{className:"space-y-4 bg-background",children:(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsx)("p",{className:"mb-2 text-sm font-semibold text-foreground",children:"Questions"}),(0,n.jsx)("ol",{className:"grid gap-3 text-sm text-foreground",children:te.questions.map((e,t)=>{let r,a,i=te.answers[t];return(0,n.jsxs)("li",{children:[(0,n.jsx)("p",{children:(a=(r=e.trim()).replace(/^question\s*\d+\s*[:.)-]?\s*/i,"").replace(/^q\s*\d+\s*[:.)-]?\s*/i,"").replace(/^\d+\s*[:.)-]\s*/,"").trim(),`${t+1}. ${a||r}`)}),ts&&i?(0,n.jsx)("p",{className:"mt-1 font-bold text-[#859BB2]",children:eu(i)}):null]},`${te.id}-q-${t}`)})})]})}):(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:"No listening dataset loaded yet."}),(0,n.jsx)("div",{className:"flex justify-end",children:(0,n.jsx)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:r8,disabled:!te,children:ts?"Hide Answers":"Show Answers"})})]}):"speaking"===e.key?(0,n.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsxs)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground",onClick:na,children:[(0,n.jsx)(f,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Refresh"})]}),(0,n.jsx)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:()=>void ni(tm?.topic||"","prompt"),disabled:nC,children:tw?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(h,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Stop Task Card"})]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(y,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Play Task Card"})]})})]}),tg&&(0,n.jsx)("p",{className:"text-xs text-muted-foreground",children:tg}),tm?(0,n.jsxs)("div",{className:"space-y-4 bg-background",children:[(0,n.jsxs)("div",{className:"rounded-md border border-border bg-card p-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsx)("p",{className:"text-sm font-semibold text-foreground",children:"My Answer"}),(0,n.jsxs)("div",{className:"flex items-center gap-3 text-xs text-muted-foreground",children:[tm.topicField?(0,n.jsxs)("p",{className:"inline-flex items-center gap-1",children:[(0,n.jsx)("span",{className:"font-semibold text-foreground",children:"Field:"}),(0,n.jsx)("span",{className:"truncate",children:tm.topicField})]}):null,(0,n.jsxs)("p",{children:[tA,"s / ",120,"s"]})]})]}),(0,n.jsx)("div",{className:"mt-2 h-2 w-full rounded bg-muted",children:(0,n.jsx)("div",{className:"h-2 rounded bg-primary transition-all",style:{width:`${Math.max(4,tR)}%`}})}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[(0,n.jsx)("button",{type:"button",className:"inline-flex box-border min-h-[2.625rem] min-w-0 items-center justify-center rounded-md bg-primary px-3 py-2 text-center font-semibold leading-tight whitespace-normal text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:()=>void nu(),disabled:th,children:"recording"===tk?"Complete":"recorded"===tk?"Record Again":"Record My Answer"}),(0,n.jsx)("button",{type:"button",className:"inline-flex box-border min-h-[2.625rem] min-w-0 items-center justify-center rounded-md bg-primary px-3 py-2 text-center font-semibold leading-tight whitespace-normal text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:nm,disabled:!tT||"recording"===tk,children:tW?"Stop Listening":"Listen My Answer"})]})]}),(0,n.jsx)("div",{className:"flex justify-end",children:(0,n.jsx)("button",{type:"button",className:"inline-flex box-border h-[2.625rem] min-w-0 items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-0 font-semibold text-primary-foreground active:bg-accent active:text-accent-foreground disabled:bg-primary/60 disabled:text-primary-foreground disabled:opacity-100",onClick:()=>{tm&&eK(tm),ni(tm?.modelAnswer||"","model")},disabled:nM,children:tx?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(h,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Stop Model Answer"})]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(y,{className:"h-3.5 w-3.5","aria-hidden":"true"}),(0,n.jsx)("span",{children:"Play Model Answer"})]})})})]}):(0,n.jsx)("p",{className:"text-sm text-muted-foreground",children:"No speaking prompt loaded yet."})]}):(0,n.jsx)("p",{className:"mt-2 text-sm text-muted-foreground",children:e.description})]},e.key))})]}),(0,n.jsx)("footer",{className:"mt-8 border-t border-border pt-4 text-sm text-muted-foreground",children:(0,n.jsx)("div",{className:"mx-auto flex w-full max-w-5xl items-center px-4",children:(0,n.jsx)("a",{href:"mailto:formelog00@gmail.com",className:"min-w-0 w-full text-right no-underline hover:no-underline active:no-underline",children:"formelog00@gmail.com"})})}),(0,n.jsx)("nav",{"aria-label":"Main section quick navigation",className:"fixed inset-x-0 bottom-0 z-30 border-t border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/85",children:(0,n.jsx)("div",{className:"mx-auto grid w-full max-w-5xl grid-cols-5 gap-1 px-4 py-2",children:b.map(e=>{let t=e.icon;return(0,n.jsx)("button",{type:"button",className:"inline-flex min-h-14 items-center justify-center rounded-md px-2 py-2 text-foreground active:bg-accent active:text-accent-foreground",onClick:()=>{var t;let r;t=e.key,r=document.getElementById(`section-${t}`),r?.scrollIntoView({behavior:"smooth",block:"start"})},"aria-label":`Go to ${e.label} section`,title:e.label,children:(0,n.jsx)(t,{className:"h-5 w-5","aria-hidden":"true"})},e.key)})})})]})}},9416:(e,t,r)=>{Promise.resolve().then(r.bind(r,1206))}},e=>{e.O(0,[64,622,358],()=>e(e.s=9416)),_N_E=e.O()}]);