[{"content":"Choose a character set and get started. The character is shown — pick the correct romaji reading.\nBasic 46 All Characters Start Quiz ▶ Question 1 of 10 ? Click the character to hear it ","permalink":"https://japaneseunlocked.com/hiragana/quiz/","summary":"\u003cp\u003eChoose a character set and get started. The character is shown — pick the correct romaji reading.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-basic\" onclick=\"setMode('basic')\"\u003eBasic 46\u003c/button\u003e\n    \u003cbutton class=\"quiz-mode-btn\" id=\"btn-all\" onclick=\"setMode('all')\"\u003eAll Characters\u003c/button\u003e\n    \u003cbutton class=\"quiz-mode-btn\" id=\"btn-start\" onclick=\"startQuiz()\" style=\"margin-left:auto\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick the character to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst BASIC = [\n  {kana:'あ',romaji:'a'},{kana:'い',romaji:'i'},{kana:'う',romaji:'u'},{kana:'え',romaji:'e'},{kana:'お',romaji:'o'},\n  {kana:'か',romaji:'ka'},{kana:'き',romaji:'ki'},{kana:'く',romaji:'ku'},{kana:'け',romaji:'ke'},{kana:'こ',romaji:'ko'},\n  {kana:'さ',romaji:'sa'},{kana:'し',romaji:'shi'},{kana:'す',romaji:'su'},{kana:'せ',romaji:'se'},{kana:'そ',romaji:'so'},\n  {kana:'た',romaji:'ta'},{kana:'ち',romaji:'chi'},{kana:'つ',romaji:'tsu'},{kana:'て',romaji:'te'},{kana:'と',romaji:'to'},\n  {kana:'な',romaji:'na'},{kana:'に',romaji:'ni'},{kana:'ぬ',romaji:'nu'},{kana:'ね',romaji:'ne'},{kana:'の',romaji:'no'},\n  {kana:'は',romaji:'ha'},{kana:'ひ',romaji:'hi'},{kana:'ふ',romaji:'fu'},{kana:'へ',romaji:'he'},{kana:'ほ',romaji:'ho'},\n  {kana:'ま',romaji:'ma'},{kana:'み',romaji:'mi'},{kana:'む',romaji:'mu'},{kana:'め',romaji:'me'},{kana:'も',romaji:'mo'},\n  {kana:'や',romaji:'ya'},{kana:'ゆ',romaji:'yu'},{kana:'よ',romaji:'yo'},\n  {kana:'ら',romaji:'ra'},{kana:'り',romaji:'ri'},{kana:'る',romaji:'ru'},{kana:'れ',romaji:'re'},{kana:'ろ',romaji:'ro'},\n  {kana:'わ',romaji:'wa'},{kana:'を',romaji:'wo'},{kana:'ん',romaji:'n'}\n];\n\nconst EXTENDED = [\n  {kana:'が',romaji:'ga'},{kana:'ぎ',romaji:'gi'},{kana:'ぐ',romaji:'gu'},{kana:'げ',romaji:'ge'},{kana:'ご',romaji:'go'},\n  {kana:'ざ',romaji:'za'},{kana:'じ',romaji:'ji'},{kana:'ず',romaji:'zu'},{kana:'ぜ',romaji:'ze'},{kana:'ぞ',romaji:'zo'},\n  {kana:'だ',romaji:'da'},{kana:'で',romaji:'de'},{kana:'ど',romaji:'do'},\n  {kana:'ば',romaji:'ba'},{kana:'び',romaji:'bi'},{kana:'ぶ',romaji:'bu'},{kana:'べ',romaji:'be'},{kana:'ぼ',romaji:'bo'},\n  {kana:'ぱ',romaji:'pa'},{kana:'ぴ',romaji:'pi'},{kana:'ぷ',romaji:'pu'},{kana:'ぺ',romaji:'pe'},{kana:'ぽ',romaji:'po'},\n  {kana:'きゃ',romaji:'kya'},{kana:'きゅ',romaji:'kyu'},{kana:'きょ',romaji:'kyo'},\n  {kana:'しゃ',romaji:'sha'},{kana:'しゅ',romaji:'shu'},{kana:'しょ',romaji:'sho'},\n  {kana:'ちゃ',romaji:'cha'},{kana:'ちゅ',romaji:'chu'},{kana:'ちょ',romaji:'cho'},\n  {kana:'にゃ',romaji:'nya'},{kana:'にゅ',romaji:'nyu'},{kana:'にょ',romaji:'nyo'},\n  {kana:'ひゃ',romaji:'hya'},{kana:'ひゅ',romaji:'hyu'},{kana:'ひょ',romaji:'hyo'},\n  {kana:'みゃ',romaji:'mya'},{kana:'みゅ',romaji:'myu'},{kana:'みょ',romaji:'myo'},\n  {kana:'りゃ',romaji:'rya'},{kana:'りゅ',romaji:'ryu'},{kana:'りょ',romaji:'ryo'}\n];\n\nlet mode = 'basic';\nlet pool = [];\nlet questions = [];\nlet currentIdx = 0;\nlet score = 0;\nlet answered = false;\n\nfunction setMode(m) {\n  mode = m;\n  document.getElementById('btn-basic').classList.toggle('active', m === 'basic');\n  document.getElementById('btn-all').classList.toggle('active', m === 'all');\n}\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  pool = mode === 'basic' ? BASIC : BASIC.concat(EXTENDED);\n  questions = shuffle(pool).slice(0, 10);\n  currentIdx = 0;\n  score = 0;\n  answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  const q = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = q.kana;\n  document.getElementById('quiz-feedback').textContent = '';\n\n  // Build 4 options: 1 correct + 3 wrong\n  const wrongs = shuffle(pool.filter(function(x){ return x.romaji !== q.romaji; })).slice(0, 3);\n  const options = shuffle([q].concat(wrongs));\n\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.romaji;\n    btn.onclick = function(){ checkAnswer(btn, opt.romaji, q); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.romaji;\n  if (isCorrect) {\n    btn.classList.add('correct');\n    score++;\n    speak(q.kana);\n    document.getElementById('quiz-feedback').textContent = '✓ Correct!';\n  } else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.romaji;\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){\n      if (b.textContent === q.romaji) b.classList.add('correct');\n    });\n    speak(q.kana);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){\n    currentIdx++;\n    if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); }\n  }, 1300);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msgs = {\n    100: '完璧！ Perfect score!',\n    90:  'すごい！ Excellent!',\n    80:  'よくできました！ Great work!',\n    70:  'いいね！ Good job!',\n    60:  'まあまあ！ Not bad — keep going!',\n    0:   'もう一度！ Keep practicing!'\n  };\n  const msg = msgs[pct] || (pct \u003e= 60 ? msgs[60] : msgs[0]);\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e' +\n    '\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e' +\n    '\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e' +\n    '\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e' +\n    '\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick the character to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() {\n  const txt = document.getElementById('quiz-char').textContent;\n  if (txt \u0026\u0026 txt !== '?') speak(txt);\n}\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP';\n  u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"Hiragana Quiz"},{"content":"A kanji is shown — pick the correct English meaning.\nStart Quiz ▶ Question 1 of 10 ? Click the kanji to hear it ","permalink":"https://japaneseunlocked.com/kanji/quiz/","summary":"\u003cp\u003eA kanji is shown — pick the correct English meaning.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick the kanji to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst KANJI = [\n  {kanji:'日',meaning:'day / sun'},{kanji:'月',meaning:'month / moon'},{kanji:'火',meaning:'fire'},\n  {kanji:'水',meaning:'water'},{kanji:'木',meaning:'tree'},{kanji:'金',meaning:'gold / money'},\n  {kanji:'土',meaning:'earth / soil'},{kanji:'人',meaning:'person'},{kanji:'女',meaning:'woman'},\n  {kanji:'男',meaning:'man'},{kanji:'子',meaning:'child'},{kanji:'学',meaning:'study'},\n  {kanji:'先',meaning:'previous / ahead'},{kanji:'生',meaning:'life / birth'},{kanji:'山',meaning:'mountain'},\n  {kanji:'川',meaning:'river'},{kanji:'田',meaning:'rice field'},{kanji:'天',meaning:'heaven / sky'},\n  {kanji:'空',meaning:'sky / empty'},{kanji:'雨',meaning:'rain'},{kanji:'電',meaning:'electricity'},\n  {kanji:'車',meaning:'car / vehicle'},{kanji:'校',meaning:'school'},{kanji:'友',meaning:'friend'},\n  {kanji:'本',meaning:'book / origin'},{kanji:'語',meaning:'language / word'},{kanji:'読',meaning:'read'},\n  {kanji:'書',meaning:'write'},{kanji:'聞',meaning:'hear / ask'},{kanji:'話',meaning:'talk / story'},\n  {kanji:'買',meaning:'buy'},{kanji:'食',meaning:'eat / food'},{kanji:'飲',meaning:'drink'},\n  {kanji:'行',meaning:'go'},{kanji:'来',meaning:'come'},{kanji:'見',meaning:'see / look'},\n  {kanji:'立',meaning:'stand'},{kanji:'入',meaning:'enter'},{kanji:'出',meaning:'exit / come out'},\n  {kanji:'大',meaning:'big / large'},{kanji:'小',meaning:'small'},{kanji:'中',meaning:'middle / inside'},\n  {kanji:'長',meaning:'long / leader'},{kanji:'白',meaning:'white'},{kanji:'黒',meaning:'black'},\n  {kanji:'赤',meaning:'red'},{kanji:'青',meaning:'blue / green'},{kanji:'名',meaning:'name'},\n  {kanji:'年',meaning:'year'},{kanji:'時',meaning:'time / hour'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(KANJI).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  const q = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = q.kanji;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(KANJI.filter(function(x){ return x.meaning !== q.meaning; })).slice(0, 3);\n  const options = shuffle([q].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.meaning;\n    btn.style.fontSize = '0.88rem';\n    btn.onclick = function(){ checkAnswer(btn, opt.meaning, q); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.meaning;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.kanji); document.getElementById('quiz-feedback').textContent = '✓ Correct!'; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.meaning;\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.meaning) b.classList.add('correct'); });\n    speak(q.kanji);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1400);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick the kanji to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() {\n  const txt = document.getElementById('quiz-char').textContent;\n  if (txt \u0026\u0026 txt !== '?') speak(txt);\n}\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"Kanji Quiz"},{"content":"A katakana character is shown — pick the correct romaji reading.\nBasic 46 All Characters Start Quiz ▶ Question 1 of 10 ? Click the character to hear it ","permalink":"https://japaneseunlocked.com/katakana/quiz/","summary":"\u003cp\u003eA katakana character is shown — pick the correct romaji reading.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-basic\" onclick=\"setMode('basic')\"\u003eBasic 46\u003c/button\u003e\n    \u003cbutton class=\"quiz-mode-btn\" id=\"btn-all\" onclick=\"setMode('all')\"\u003eAll Characters\u003c/button\u003e\n    \u003cbutton class=\"quiz-mode-btn\" id=\"btn-start\" onclick=\"startQuiz()\" style=\"margin-left:auto\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick the character to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst BASIC = [\n  {kana:'ア',romaji:'a'},{kana:'イ',romaji:'i'},{kana:'ウ',romaji:'u'},{kana:'エ',romaji:'e'},{kana:'オ',romaji:'o'},\n  {kana:'カ',romaji:'ka'},{kana:'キ',romaji:'ki'},{kana:'ク',romaji:'ku'},{kana:'ケ',romaji:'ke'},{kana:'コ',romaji:'ko'},\n  {kana:'サ',romaji:'sa'},{kana:'シ',romaji:'shi'},{kana:'ス',romaji:'su'},{kana:'セ',romaji:'se'},{kana:'ソ',romaji:'so'},\n  {kana:'タ',romaji:'ta'},{kana:'チ',romaji:'chi'},{kana:'ツ',romaji:'tsu'},{kana:'テ',romaji:'te'},{kana:'ト',romaji:'to'},\n  {kana:'ナ',romaji:'na'},{kana:'ニ',romaji:'ni'},{kana:'ヌ',romaji:'nu'},{kana:'ネ',romaji:'ne'},{kana:'ノ',romaji:'no'},\n  {kana:'ハ',romaji:'ha'},{kana:'ヒ',romaji:'hi'},{kana:'フ',romaji:'fu'},{kana:'ヘ',romaji:'he'},{kana:'ホ',romaji:'ho'},\n  {kana:'マ',romaji:'ma'},{kana:'ミ',romaji:'mi'},{kana:'ム',romaji:'mu'},{kana:'メ',romaji:'me'},{kana:'モ',romaji:'mo'},\n  {kana:'ヤ',romaji:'ya'},{kana:'ユ',romaji:'yu'},{kana:'ヨ',romaji:'yo'},\n  {kana:'ラ',romaji:'ra'},{kana:'リ',romaji:'ri'},{kana:'ル',romaji:'ru'},{kana:'レ',romaji:'re'},{kana:'ロ',romaji:'ro'},\n  {kana:'ワ',romaji:'wa'},{kana:'ヲ',romaji:'wo'},{kana:'ン',romaji:'n'}\n];\n\nconst EXTENDED = [\n  {kana:'ガ',romaji:'ga'},{kana:'ギ',romaji:'gi'},{kana:'グ',romaji:'gu'},{kana:'ゲ',romaji:'ge'},{kana:'ゴ',romaji:'go'},\n  {kana:'ザ',romaji:'za'},{kana:'ジ',romaji:'ji'},{kana:'ズ',romaji:'zu'},{kana:'ゼ',romaji:'ze'},{kana:'ゾ',romaji:'zo'},\n  {kana:'ダ',romaji:'da'},{kana:'デ',romaji:'de'},{kana:'ド',romaji:'do'},\n  {kana:'バ',romaji:'ba'},{kana:'ビ',romaji:'bi'},{kana:'ブ',romaji:'bu'},{kana:'ベ',romaji:'be'},{kana:'ボ',romaji:'bo'},\n  {kana:'パ',romaji:'pa'},{kana:'ピ',romaji:'pi'},{kana:'プ',romaji:'pu'},{kana:'ペ',romaji:'pe'},{kana:'ポ',romaji:'po'},\n  {kana:'キャ',romaji:'kya'},{kana:'キュ',romaji:'kyu'},{kana:'キョ',romaji:'kyo'},\n  {kana:'シャ',romaji:'sha'},{kana:'シュ',romaji:'shu'},{kana:'ショ',romaji:'sho'},\n  {kana:'チャ',romaji:'cha'},{kana:'チュ',romaji:'chu'},{kana:'チョ',romaji:'cho'},\n  {kana:'ニャ',romaji:'nya'},{kana:'ニュ',romaji:'nyu'},{kana:'ニョ',romaji:'nyo'},\n  {kana:'ヒャ',romaji:'hya'},{kana:'ヒュ',romaji:'hyu'},{kana:'ヒョ',romaji:'hyo'},\n  {kana:'ミャ',romaji:'mya'},{kana:'ミュ',romaji:'myu'},{kana:'ミョ',romaji:'myo'},\n  {kana:'リャ',romaji:'rya'},{kana:'リュ',romaji:'ryu'},{kana:'リョ',romaji:'ryo'}\n];\n\nlet mode = 'basic';\nlet pool = [], questions = [], currentIdx = 0, score = 0, answered = false;\n\nfunction setMode(m) {\n  mode = m;\n  document.getElementById('btn-basic').classList.toggle('active', m === 'basic');\n  document.getElementById('btn-all').classList.toggle('active', m === 'all');\n}\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  pool = mode === 'basic' ? BASIC : BASIC.concat(EXTENDED);\n  questions = shuffle(pool).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  const q = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = q.kana;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(pool.filter(function(x){ return x.romaji !== q.romaji; })).slice(0, 3);\n  const options = shuffle([q].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.romaji;\n    btn.onclick = function(){ checkAnswer(btn, opt.romaji, q); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.romaji;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.kana); document.getElementById('quiz-feedback').textContent = '✓ Correct!'; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.romaji;\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.romaji) b.classList.add('correct'); });\n    speak(q.kana);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1300);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick the character to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() {\n  const txt = document.getElementById('quiz-char').textContent;\n  if (txt \u0026\u0026 txt !== '?') speak(txt);\n}\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"Katakana Quiz"},{"content":"A Japanese word is shown — pick the correct English meaning.\nStart Quiz ▶ Question 1 of 10 ? Click to hear it ","permalink":"https://japaneseunlocked.com/jlpt/n1/quiz/","summary":"\u003cp\u003eA Japanese word is shown — pick the correct English meaning.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2rem;line-height:1.3\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst VOCAB = [\n  {jp:'怠る',read:'okotaru',en:'to neglect / be negligent'},{jp:'顧みる',read:'kaerimiru',en:'to reflect on / look back'},\n  {jp:'阻む',read:'habamu',en:'to obstruct / prevent'},{jp:'担う',read:'ninau',en:'to take on / bear responsibility'},\n  {jp:'覆す',read:'kutsugaesu',en:'to overturn / overthrow'},{jp:'培う',read:'tsuchikau',en:'to cultivate / foster'},\n  {jp:'模索する',read:'mosaku suru',en:'to grope for / search out'},{jp:'克服する',read:'kokufuku suru',en:'to overcome'},\n  {jp:'是正する',read:'zesei suru',en:'to correct / rectify'},{jp:'懸念する',read:'kenen suru',en:'to be concerned about'},\n  {jp:'吟味する',read:'ginmi suru',en:'to scrutinise / examine closely'},{jp:'危惧する',read:'kigu suru',en:'to fear / be apprehensive'},\n  {jp:'企てる',read:'kuwadateru',en:'to plan / scheme'},{jp:'抱く',read:'idaku',en:'to hold / harbour feelings'},\n  {jp:'損なう',read:'sokonau',en:'to damage / impair'},\n  {jp:'葛藤',read:'kattou',en:'conflict / inner struggle'},{jp:'懸念',read:'kenen',en:'concern / apprehension'},\n  {jp:'逆説',read:'gyakusetsu',en:'paradox'},{jp:'弊害',read:'heigai',en:'harmful effect / abuse'},\n  {jp:'根拠',read:'konkyo',en:'basis / grounds'},{jp:'見解',read:'kenkai',en:'view / opinion'},\n  {jp:'動向',read:'doukou',en:'trend / movement'},{jp:'本質',read:'honshitsu',en:'essence / true nature'},\n  {jp:'趣旨',read:'shushi',en:'gist / purpose'},{jp:'誤解',read:'gokai',en:'misunderstanding'},\n  {jp:'齟齬',read:'sogo',en:'discrepancy / mismatch'},{jp:'忖度',read:'sontaku',en:'reading someone\\'s wishes'},\n  {jp:'曖昧',read:'aimai',en:'ambiguity / vagueness'},{jp:'概要',read:'gaiyou',en:'outline / summary'},\n  {jp:'慣例',read:'kanrei',en:'precedent / convention'},\n  {jp:'高尚な',read:'koushou na',en:'noble / refined'},{jp:'卑劣な',read:'hiretsu na',en:'despicable / mean'},\n  {jp:'冷淡な',read:'reitan na',en:'cold / indifferent'},{jp:'無謀な',read:'mubou na',en:'reckless / rash'},\n  {jp:'狡猾な',read:'koukatsu na',en:'cunning / sly'},{jp:'崇高な',read:'suukou na',en:'sublime / lofty'},\n  {jp:'一石二鳥',read:'isseki nichou',en:'killing two birds with one stone'},\n  {jp:'試行錯誤',read:'shikou sakugo',en:'trial and error'},\n  {jp:'以心伝心',read:'ishin denshin',en:'unspoken understanding'},\n  {jp:'自業自得',read:'jigou jitoku',en:'reaping what you sow'},\n  {jp:'一期一会',read:'ichi go ichi e',en:'once in a lifetime encounter'},\n  {jp:'臨機応変',read:'rinki ouhen',en:'adapting flexibly to circumstances'},\n  {jp:'半信半疑',read:'hanshin hangi',en:'half-believing / doubtful'},\n  {jp:'喜怒哀楽',read:'ki do ai raku',en:'the full range of human emotions'},\n  {jp:'五里霧中',read:'gori muchuu',en:'at a complete loss / in the dark'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false, currentItem = null;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(VOCAB).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  currentItem = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = currentItem.jp;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(VOCAB.filter(function(x){ return x.en !== currentItem.en; })).slice(0, 3);\n  const options = shuffle([currentItem].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.en;\n    btn.style.fontSize = '0.82rem';\n    btn.onclick = function(){ checkAnswer(btn, opt.en, currentItem); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.en;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.read); document.getElementById('quiz-feedback').textContent = '✓ Correct! ' + q.read; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.en + ' (' + q.read + ')';\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.en) b.classList.add('correct'); });\n    speak(q.read);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1500);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2rem;line-height:1.3\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() { if (currentItem) speak(currentItem.read); }\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"N1 Vocab Quiz"},{"content":"A Japanese word is shown — pick the correct English meaning.\nStart Quiz ▶ Question 1 of 10 ? Click to hear it ","permalink":"https://japaneseunlocked.com/jlpt/n2/quiz/","summary":"\u003cp\u003eA Japanese word is shown — pick the correct English meaning.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2rem;line-height:1.3\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst VOCAB = [\n  {jp:'反映する',read:'hanei suru',en:'to reflect / mirror'},{jp:'示す',read:'shimesu',en:'to show / indicate'},\n  {jp:'認める',read:'mitomeru',en:'to recognise / admit'},{jp:'求める',read:'motomeru',en:'to demand / seek'},\n  {jp:'述べる',read:'noberu',en:'to state / mention'},{jp:'導く',read:'michibiku',en:'to lead / guide'},\n  {jp:'判断する',read:'handan suru',en:'to judge / determine'},{jp:'確認する',read:'kakunin suru',en:'to confirm / verify'},\n  {jp:'実現する',read:'jitsugen suru',en:'to realise / achieve'},{jp:'解決する',read:'kaiketsu suru',en:'to solve / resolve'},\n  {jp:'失う',read:'ushinau',en:'to lose'},{jp:'含む',read:'fukumu',en:'to contain / include'},\n  {jp:'主張する',read:'shuchou suru',en:'to insist / claim'},{jp:'提案する',read:'teian suru',en:'to propose / suggest'},\n  {jp:'指摘する',read:'shiteki suru',en:'to point out'},{jp:'促す',read:'unagasu',en:'to urge / encourage'},\n  {jp:'従う',read:'shitagau',en:'to follow / obey'},{jp:'比較する',read:'hikaku suru',en:'to compare'},\n  {jp:'依頼する',read:'irai suru',en:'to request / commission'},{jp:'承認する',read:'shounin suru',en:'to approve / sanction'},\n  {jp:'義務',read:'gimu',en:'obligation / duty'},{jp:'権利',read:'kenri',en:'right / entitlement'},\n  {jp:'責任',read:'sekinin',en:'responsibility'},{jp:'優先',read:'yuusen',en:'priority'},\n  {jp:'条件',read:'jouken',en:'condition / requirement'},{jp:'基準',read:'kijun',en:'standard / criterion'},\n  {jp:'範囲',read:'hani',en:'range / scope'},{jp:'限界',read:'genkai',en:'limit / boundary'},\n  {jp:'目標',read:'mokuhyou',en:'goal / target'},{jp:'方針',read:'houshin',en:'policy / direction'},\n  {jp:'背景',read:'haikei',en:'background / context'},{jp:'状況',read:'joukyou',en:'situation / circumstances'},\n  {jp:'内容',read:'naiyou',en:'content / substance'},{jp:'手段',read:'shudan',en:'means / method'},\n  {jp:'課題',read:'kadai',en:'task / challenge'},{jp:'傾向',read:'keikou',en:'tendency / trend'},\n  {jp:'影響',read:'eikyou',en:'influence / effect'},{jp:'前提',read:'zentei',en:'premise / prerequisite'},\n  {jp:'矛盾',read:'mujun',en:'contradiction'},{jp:'概念',read:'gainen',en:'concept / notion'},\n  {jp:'妥協',read:'dakyou',en:'compromise'},{jp:'批判',read:'hihan',en:'criticism'},\n  {jp:'積極的な',read:'sekkyokuteki na',en:'proactive / positive'},{jp:'消極的な',read:'shoukyokuteki na',en:'passive / negative'},\n  {jp:'合理的な',read:'gouriteki na',en:'rational / logical'},{jp:'効率的な',read:'kouritsuteki na',en:'efficient'},\n  {jp:'具体的な',read:'gutaiteki na',en:'concrete / specific'},{jp:'抽象的な',read:'chuushouteki na',en:'abstract'},\n  {jp:'客観的な',read:'kyakukanteki na',en:'objective'},{jp:'主観的な',read:'shukanteki na',en:'subjective'},\n  {jp:'したがって',read:'shitagatte',en:'therefore / consequently'},{jp:'ところが',read:'tokoro ga',en:'however (unexpected)'},\n  {jp:'さらに',read:'sara ni',en:'furthermore / moreover'},{jp:'むしろ',read:'mushiro',en:'rather / instead'},\n  {jp:'すなわち',read:'sunawachi',en:'namely / that is to say'},{jp:'いわば',read:'iwaba',en:'so to speak'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false, currentItem = null;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(VOCAB).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  currentItem = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = currentItem.jp;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(VOCAB.filter(function(x){ return x.en !== currentItem.en; })).slice(0, 3);\n  const options = shuffle([currentItem].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.en;\n    btn.style.fontSize = '0.82rem';\n    btn.onclick = function(){ checkAnswer(btn, opt.en, currentItem); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.en;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.read); document.getElementById('quiz-feedback').textContent = '✓ Correct! ' + q.read; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.en + ' (' + q.read + ')';\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.en) b.classList.add('correct'); });\n    speak(q.read);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1500);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2rem;line-height:1.3\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() { if (currentItem) speak(currentItem.read); }\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"N2 Vocab Quiz"},{"content":"A Japanese word is shown — pick the correct English meaning.\nStart Quiz ▶ Question 1 of 10 ? Click to hear it ","permalink":"https://japaneseunlocked.com/jlpt/n3/quiz/","summary":"\u003cp\u003eA Japanese word is shown — pick the correct English meaning.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.2rem;line-height:1.3\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst VOCAB = [\n  {jp:'受ける',read:'ukeru',en:'to receive / take an exam'},{jp:'断る',read:'kotowaru',en:'to refuse / decline'},\n  {jp:'比べる',read:'kuraberu',en:'to compare'},{jp:'探す',read:'sagasu',en:'to search for'},\n  {jp:'見つける',read:'mitsukeru',en:'to find'},{jp:'選ぶ',read:'erabu',en:'to choose / select'},\n  {jp:'消える',read:'kieru',en:'to disappear'},{jp:'増える',read:'fueru',en:'to increase'},\n  {jp:'減る',read:'heru',en:'to decrease'},{jp:'壊れる',read:'kowareru',en:'to break (intransitive)'},\n  {jp:'壊す',read:'kowasu',en:'to break (transitive)'},{jp:'直す',read:'naosu',en:'to fix / correct'},\n  {jp:'倒れる',read:'taoreru',en:'to fall over / collapse'},{jp:'驚く',read:'odoroku',en:'to be surprised'},\n  {jp:'喜ぶ',read:'yorokobu',en:'to be pleased / rejoice'},{jp:'悩む',read:'nayamu',en:'to be troubled'},\n  {jp:'諦める',read:'akirameru',en:'to give up'},{jp:'頑張る',read:'ganbaru',en:'to do one\\'s best'},\n  {jp:'慣れる',read:'nareru',en:'to get used to'},{jp:'変える',read:'kaeru',en:'to change (transitive)'},\n  {jp:'起こる',read:'okoru',en:'to happen / occur'},{jp:'決まる',read:'kimaru',en:'to be decided'},\n  {jp:'細い',read:'hosoi',en:'thin / narrow'},{jp:'太い',read:'futoi',en:'thick / fat'},\n  {jp:'深い',read:'fukai',en:'deep'},{jp:'浅い',read:'asai',en:'shallow'},\n  {jp:'固い',read:'katai',en:'hard / firm'},{jp:'柔らかい',read:'yawarakai',en:'soft'},\n  {jp:'珍しい',read:'mezurashii',en:'rare / unusual'},{jp:'恥ずかしい',read:'hazukashii',en:'embarrassing / shy'},\n  {jp:'嬉しい',read:'ureshii',en:'happy / pleased'},{jp:'悲しい',read:'kanashii',en:'sad'},\n  {jp:'怖い',read:'kowai',en:'scary / frightening'},{jp:'眠い',read:'nemui',en:'sleepy'},\n  {jp:'様々な',read:'samazama na',en:'various / diverse'},{jp:'正確な',read:'seikaku na',en:'accurate / precise'},\n  {jp:'適切な',read:'tekisetsu na',en:'appropriate / suitable'},{jp:'豊かな',read:'yutaka na',en:'rich / abundant'},\n  {jp:'無駄な',read:'muda na',en:'wasteful / pointless'},{jp:'自由な',read:'jiyuu na',en:'free / unrestricted'},\n  {jp:'必要な',read:'hitsuyou na',en:'necessary'},{jp:'不思議な',read:'fushigi na',en:'mysterious / strange'},\n  {jp:'性格',read:'seikaku',en:'personality / character'},{jp:'事故',read:'jiko',en:'accident'},\n  {jp:'事件',read:'jiken',en:'incident / case'},{jp:'原因',read:'genin',en:'cause / reason'},\n  {jp:'関係',read:'kankei',en:'relationship / connection'},{jp:'努力',read:'doryoku',en:'effort'},\n  {jp:'注意',read:'chuui',en:'attention / caution'},{jp:'準備',read:'junbi',en:'preparation'},\n  {jp:'計画',read:'keikaku',en:'plan / project'},{jp:'自信',read:'jishin',en:'confidence'},\n  {jp:'安心',read:'anshin',en:'relief / peace of mind'},{jp:'人口',read:'jinkou',en:'population'},\n  {jp:'自然',read:'shizen',en:'nature'},{jp:'科学',read:'kagaku',en:'science'},\n  {jp:'習慣',read:'shuukan',en:'habit / custom'},{jp:'目的',read:'mokuteki',en:'purpose / goal'},\n  {jp:'やっと',read:'yatto',en:'finally / at last'},{jp:'すっかり',read:'sukkari',en:'completely / entirely'},\n  {jp:'だんだん',read:'dandan',en:'gradually'},{jp:'きっと',read:'kitto',en:'surely / certainly'},\n  {jp:'まるで',read:'marude',en:'as if / just like'},{jp:'ちゃんと',read:'chanto',en:'properly / correctly'},\n  {jp:'どんどん',read:'dondon',en:'rapidly / steadily'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false, currentItem = null;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(VOCAB).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  currentItem = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = currentItem.jp;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(VOCAB.filter(function(x){ return x.en !== currentItem.en; })).slice(0, 3);\n  const options = shuffle([currentItem].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.en;\n    btn.style.fontSize = '0.85rem';\n    btn.onclick = function(){ checkAnswer(btn, opt.en, currentItem); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.en;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.read); document.getElementById('quiz-feedback').textContent = '✓ Correct! ' + q.read; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.en + ' (' + q.read + ')';\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.en) b.classList.add('correct'); });\n    speak(q.read);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1500);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.2rem;line-height:1.3\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() { if (currentItem) speak(currentItem.read); }\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"N3 Vocab Quiz"},{"content":"A Japanese word is shown — pick the correct English meaning.\nStart Quiz ▶ Question 1 of 10 ? Click to hear it ","permalink":"https://japaneseunlocked.com/jlpt/n4/quiz/","summary":"\u003cp\u003eA Japanese word is shown — pick the correct English meaning.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.2rem;line-height:1.3\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst VOCAB = [\n  {jp:'覚える',read:'oboeru',en:'to memorise / remember'},{jp:'忘れる',read:'wasureru',en:'to forget'},\n  {jp:'教える',read:'oshieru',en:'to teach / tell'},{jp:'習う',read:'narau',en:'to learn (from someone)'},\n  {jp:'決める',read:'kimeru',en:'to decide'},{jp:'変わる',read:'kawaru',en:'to change'},\n  {jp:'続ける',read:'tsuzukeru',en:'to continue'},{jp:'終わる',read:'owaru',en:'to end / finish'},\n  {jp:'始まる',read:'hajimaru',en:'to begin'},{jp:'集まる',read:'atsumaru',en:'to gather / assemble'},\n  {jp:'心配する',read:'shinpai suru',en:'to worry'},{jp:'相談する',read:'soudan suru',en:'to consult / discuss'},\n  {jp:'連絡する',read:'renraku suru',en:'to contact / get in touch'},{jp:'説明する',read:'setsumei suru',en:'to explain'},\n  {jp:'予約する',read:'yoyaku suru',en:'to reserve / book'},\n  {jp:'もらう',read:'morau',en:'to receive'},{jp:'あげる',read:'ageru',en:'to give (to someone)'},\n  {jp:'送る',read:'okuru',en:'to send'},{jp:'届く',read:'todoku',en:'to arrive / be delivered'},\n  {jp:'便利な',read:'benri na',en:'convenient'},{jp:'大切な',read:'taisetsu na',en:'important / precious'},\n  {jp:'特別な',read:'tokubetsu na',en:'special'},{jp:'親切な',read:'shinsetsu na',en:'kind'},\n  {jp:'有名な',read:'yuumei na',en:'famous'},{jp:'安全な',read:'anzen na',en:'safe'},\n  {jp:'危険な',read:'kiken na',en:'dangerous'},{jp:'複雑な',read:'fukuzatsu na',en:'complicated'},\n  {jp:'丁寧な',read:'teinei na',en:'polite / careful'},{jp:'真面目な',read:'majime na',en:'serious / hardworking'},\n  {jp:'賑やかな',read:'nigiyaka na',en:'lively / bustling'},{jp:'静かな',read:'shizuka na',en:'quiet'},\n  {jp:'意味',read:'imi',en:'meaning'},{jp:'理由',read:'riyuu',en:'reason'},\n  {jp:'問題',read:'mondai',en:'problem / question'},{jp:'答え',read:'kotae',en:'answer'},\n  {jp:'質問',read:'shitsumon',en:'question (to ask)'},{jp:'結果',read:'kekka',en:'result'},\n  {jp:'予定',read:'yotei',en:'plan / schedule'},{jp:'気持ち',read:'kimochi',en:'feeling'},\n  {jp:'経験',read:'keiken',en:'experience'},{jp:'文化',read:'bunka',en:'culture'},\n  {jp:'言葉',read:'kotoba',en:'word / language'},{jp:'場所',read:'basho',en:'place'},\n  {jp:'旅行',read:'ryokou',en:'travel / trip'},{jp:'練習',read:'renshuu',en:'practice'},\n  {jp:'いつも',read:'itsumo',en:'always'},{jp:'たいてい',read:'taitei',en:'usually'},\n  {jp:'ときどき',read:'tokidoki',en:'sometimes'},{jp:'全然',read:'zenzen',en:'not at all'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false, currentItem = null;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(VOCAB).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  currentItem = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = currentItem.jp;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(VOCAB.filter(function(x){ return x.en !== currentItem.en; })).slice(0, 3);\n  const options = shuffle([currentItem].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.en;\n    btn.style.fontSize = '0.85rem';\n    btn.onclick = function(){ checkAnswer(btn, opt.en, currentItem); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.en;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.read); document.getElementById('quiz-feedback').textContent = '✓ Correct! ' + q.read; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.en + ' (' + q.read + ')';\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.en) b.classList.add('correct'); });\n    speak(q.read);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1500);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.2rem;line-height:1.3\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() { if (currentItem) speak(currentItem.read); }\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"N4 Vocab Quiz"},{"content":"A Japanese word is shown — pick the correct English meaning.\nStart Quiz ▶ Question 1 of 10 ? Click to hear it ","permalink":"https://japaneseunlocked.com/jlpt/n5/quiz/","summary":"\u003cp\u003eA Japanese word is shown — pick the correct English meaning.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.4rem;line-height:1.3\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst VOCAB = [\n  {jp:'私',read:'watashi',en:'I, me'},{jp:'彼',read:'kare',en:'he / boyfriend'},{jp:'彼女',read:'kanojo',en:'she / girlfriend'},\n  {jp:'友達',read:'tomodachi',en:'friend'},{jp:'先生',read:'sensei',en:'teacher'},{jp:'学生',read:'gakusei',en:'student'},\n  {jp:'今',read:'ima',en:'now'},{jp:'今日',read:'kyou',en:'today'},{jp:'明日',read:'ashita',en:'tomorrow'},\n  {jp:'昨日',read:'kinou',en:'yesterday'},{jp:'朝',read:'asa',en:'morning'},{jp:'昼',read:'hiru',en:'daytime / noon'},\n  {jp:'夜',read:'yoru',en:'night'},{jp:'毎日',read:'mainichi',en:'every day'},{jp:'来週',read:'raishuu',en:'next week'},\n  {jp:'家',read:'ie',en:'house / home'},{jp:'学校',read:'gakkou',en:'school'},{jp:'病院',read:'byouin',en:'hospital'},\n  {jp:'駅',read:'eki',en:'station'},{jp:'店',read:'mise',en:'shop / restaurant'},{jp:'図書館',read:'toshokan',en:'library'},\n  {jp:'銀行',read:'ginkou',en:'bank'},{jp:'右',read:'migi',en:'right'},{jp:'左',read:'hidari',en:'left'},\n  {jp:'前',read:'mae',en:'in front / before'},{jp:'後ろ',read:'ushiro',en:'behind'},\n  {jp:'ご飯',read:'gohan',en:'rice / meal'},{jp:'水',read:'mizu',en:'water'},{jp:'お茶',read:'ocha',en:'tea'},\n  {jp:'卵',read:'tamago',en:'egg'},{jp:'肉',read:'niku',en:'meat'},{jp:'魚',read:'sakana',en:'fish'},\n  {jp:'野菜',read:'yasai',en:'vegetables'},{jp:'果物',read:'kudamono',en:'fruit'},\n  {jp:'大きい',read:'ookii',en:'big'},{jp:'小さい',read:'chiisai',en:'small'},{jp:'新しい',read:'atarashii',en:'new'},\n  {jp:'古い',read:'furui',en:'old (things)'},{jp:'高い',read:'takai',en:'expensive / tall'},{jp:'安い',read:'yasui',en:'cheap'},\n  {jp:'おいしい',read:'oishii',en:'delicious'},{jp:'暑い',read:'atsui',en:'hot (weather)'},{jp:'寒い',read:'samui',en:'cold (weather)'},\n  {jp:'難しい',read:'muzukashii',en:'difficult'},{jp:'楽しい',read:'tanoshii',en:'fun / enjoyable'},{jp:'忙しい',read:'isogashii',en:'busy'},\n  {jp:'行きます',read:'ikimasu',en:'to go'},{jp:'来ます',read:'kimasu',en:'to come'},{jp:'帰ります',read:'kaerimasu',en:'to return home'},\n  {jp:'食べます',read:'tabemasu',en:'to eat'},{jp:'飲みます',read:'nomimasu',en:'to drink'},{jp:'見ます',read:'mimasu',en:'to see / watch'},\n  {jp:'聞きます',read:'kikimasu',en:'to listen / ask'},{jp:'読みます',read:'yomimasu',en:'to read'},{jp:'書きます',read:'kakimasu',en:'to write'},\n  {jp:'話します',read:'hanashimasu',en:'to speak / talk'},{jp:'買います',read:'kaimasu',en:'to buy'},\n  {jp:'分かります',read:'wakarimasu',en:'to understand'},{jp:'起きます',read:'okimasu',en:'to wake up'},{jp:'寝ます',read:'nemasu',en:'to sleep'},\n  {jp:'勉強します',read:'benkyou shimasu',en:'to study'},\n  {jp:'本',read:'hon',en:'book'},{jp:'電話',read:'denwa',en:'telephone'},{jp:'車',read:'kuruma',en:'car'},\n  {jp:'電車',read:'densha',en:'train'},{jp:'お金',read:'okane',en:'money'},{jp:'時計',read:'tokei',en:'watch / clock'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false, currentItem = null;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(VOCAB).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  currentItem = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = currentItem.jp;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(VOCAB.filter(function(x){ return x.en !== currentItem.en; })).slice(0, 3);\n  const options = shuffle([currentItem].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.en;\n    btn.style.fontSize = '0.85rem';\n    btn.onclick = function(){ checkAnswer(btn, opt.en, currentItem); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.en;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.read); document.getElementById('quiz-feedback').textContent = '✓ Correct! ' + q.read; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.en + ' (' + q.read + ')';\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.en) b.classList.add('correct'); });\n    speak(q.read);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1500);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.4rem;line-height:1.3\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() {\n  if (currentItem) speak(currentItem.read);\n}\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"N5 Vocab Quiz"},{"content":"A Japanese word is shown — pick the correct English meaning.\nStart Quiz ▶ Question 1 of 10 ? Click to hear it ","permalink":"https://japaneseunlocked.com/vocab/quiz/","summary":"\u003cp\u003eA Japanese word is shown — pick the correct English meaning.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.4rem;line-height:1.3\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst VOCAB = [\n  {jp:'私',read:'watashi',en:'I, me'},{jp:'彼',read:'kare',en:'he / boyfriend'},{jp:'彼女',read:'kanojo',en:'she / girlfriend'},\n  {jp:'友達',read:'tomodachi',en:'friend'},{jp:'先生',read:'sensei',en:'teacher'},{jp:'学生',read:'gakusei',en:'student'},\n  {jp:'今',read:'ima',en:'now'},{jp:'今日',read:'kyou',en:'today'},{jp:'明日',read:'ashita',en:'tomorrow'},\n  {jp:'昨日',read:'kinou',en:'yesterday'},{jp:'朝',read:'asa',en:'morning'},{jp:'昼',read:'hiru',en:'daytime / noon'},\n  {jp:'夜',read:'yoru',en:'night'},{jp:'毎日',read:'mainichi',en:'every day'},{jp:'来週',read:'raishuu',en:'next week'},\n  {jp:'家',read:'ie',en:'house / home'},{jp:'学校',read:'gakkou',en:'school'},{jp:'病院',read:'byouin',en:'hospital'},\n  {jp:'駅',read:'eki',en:'station'},{jp:'店',read:'mise',en:'shop / restaurant'},{jp:'図書館',read:'toshokan',en:'library'},\n  {jp:'銀行',read:'ginkou',en:'bank'},{jp:'右',read:'migi',en:'right'},{jp:'左',read:'hidari',en:'left'},\n  {jp:'前',read:'mae',en:'in front / before'},{jp:'後ろ',read:'ushiro',en:'behind'},\n  {jp:'ご飯',read:'gohan',en:'rice / meal'},{jp:'水',read:'mizu',en:'water'},{jp:'お茶',read:'ocha',en:'tea'},\n  {jp:'卵',read:'tamago',en:'egg'},{jp:'肉',read:'niku',en:'meat'},{jp:'魚',read:'sakana',en:'fish'},\n  {jp:'野菜',read:'yasai',en:'vegetables'},{jp:'果物',read:'kudamono',en:'fruit'},\n  {jp:'大きい',read:'ookii',en:'big'},{jp:'小さい',read:'chiisai',en:'small'},{jp:'新しい',read:'atarashii',en:'new'},\n  {jp:'古い',read:'furui',en:'old (things)'},{jp:'高い',read:'takai',en:'expensive / tall'},{jp:'安い',read:'yasui',en:'cheap'},\n  {jp:'おいしい',read:'oishii',en:'delicious'},{jp:'暑い',read:'atsui',en:'hot (weather)'},{jp:'寒い',read:'samui',en:'cold (weather)'},\n  {jp:'難しい',read:'muzukashii',en:'difficult'},{jp:'楽しい',read:'tanoshii',en:'fun / enjoyable'},{jp:'忙しい',read:'isogashii',en:'busy'},\n  {jp:'行きます',read:'ikimasu',en:'to go'},{jp:'来ます',read:'kimasu',en:'to come'},{jp:'帰ります',read:'kaerimasu',en:'to return home'},\n  {jp:'食べます',read:'tabemasu',en:'to eat'},{jp:'飲みます',read:'nomimasu',en:'to drink'},{jp:'見ます',read:'mimasu',en:'to see / watch'},\n  {jp:'聞きます',read:'kikimasu',en:'to listen / ask'},{jp:'読みます',read:'yomimasu',en:'to read'},{jp:'書きます',read:'kakimasu',en:'to write'},\n  {jp:'話します',read:'hanashimasu',en:'to speak / talk'},{jp:'買います',read:'kaimasu',en:'to buy'},\n  {jp:'分かります',read:'wakarimasu',en:'to understand'},{jp:'起きます',read:'okimasu',en:'to wake up'},{jp:'寝ます',read:'nemasu',en:'to sleep'},\n  {jp:'勉強します',read:'benkyou shimasu',en:'to study'},\n  {jp:'本',read:'hon',en:'book'},{jp:'電話',read:'denwa',en:'telephone'},{jp:'車',read:'kuruma',en:'car'},\n  {jp:'電車',read:'densha',en:'train'},{jp:'お金',read:'okane',en:'money'},{jp:'時計',read:'tokei',en:'watch / clock'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false, currentItem = null;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(VOCAB).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  currentItem = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = currentItem.jp;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(VOCAB.filter(function(x){ return x.en !== currentItem.en; })).slice(0, 3);\n  const options = shuffle([currentItem].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.en;\n    btn.style.fontSize = '0.85rem';\n    btn.onclick = function(){ checkAnswer(btn, opt.en, currentItem); };\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.en;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.read); document.getElementById('quiz-feedback').textContent = '✓ Correct! ' + q.read; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ It was: ' + q.en + ' (' + q.read + ')';\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){ if (b.textContent === q.en) b.classList.add('correct'); });\n    speak(q.read);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1500);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" title=\"Click to hear\" onclick=\"speakCurrent()\" style=\"font-size:2.4rem;line-height:1.3\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\"\u003eClick to hear it\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\"\u003e\u003c/div\u003e\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speakCurrent() {\n  if (currentItem) speak(currentItem.read);\n}\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.85;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"N5 Vocab Quiz"},{"content":"Read the English sentence — pick the correct Japanese from four options. Click any Japanese option to hear it before you choose.\nStart Quiz ▶ Question 1 of 10 ? Pick the Japanese translation below ","permalink":"https://japaneseunlocked.com/sentences/quiz/","summary":"\u003cp\u003eRead the English sentence — pick the correct Japanese from four options. Click any Japanese option to hear it before you choose.\u003c/p\u003e\n\u003cdiv class=\"quiz-wrapper\"\u003e\n  \u003cdiv class=\"quiz-mode-btns\"\u003e\n    \u003cbutton class=\"quiz-mode-btn active\" id=\"btn-start\" onclick=\"startQuiz()\"\u003eStart Quiz ▶\u003c/button\u003e\n  \u003c/div\u003e\n  \u003cdiv id=\"quiz-box\" style=\"display:none\"\u003e\n    \u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e\n    \u003cdiv id=\"quiz-char\" style=\"font-size:1.25rem;line-height:1.5;text-align:center;padding:1rem 0.5rem;min-height:3.5rem\"\u003e?\u003c/div\u003e\n    \u003cdiv id=\"quiz-char-hint\" style=\"font-size:0.76rem\"\u003ePick the Japanese translation below\u003c/div\u003e\n    \u003cdiv id=\"quiz-options\" style=\"display:grid;grid-template-columns:1fr;gap:0.6rem\"\u003e\u003c/div\u003e\n    \u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\nconst SENTENCES = [\n  {en:'Good morning',jp:'おはようございます'},{en:'Hello / Good afternoon',jp:'こんにちは'},\n  {en:'Good evening',jp:'こんばんは'},{en:'Goodbye',jp:'さようなら'},\n  {en:'Thank you',jp:'ありがとうございます'},{en:\"You're welcome\",jp:'どういたしまして'},\n  {en:'Excuse me / Sorry',jp:'すみません'},{en:\"I'm sorry\",jp:'ごめんなさい'},\n  {en:'I understand',jp:'わかります'},{en:\"I don't understand\",jp:'わかりません'},\n  {en:'One more time, please',jp:'もう一度お願いします'},{en:'Please speak slowly',jp:'ゆっくり話してください'},\n  {en:'Where is it?',jp:'どこですか？'},{en:'How much is it?',jp:'いくらですか？'},\n  {en:'What is your name?',jp:'名前は何ですか？'},{en:'I am a student',jp:'私は学生です'},\n  {en:'I am studying Japanese',jp:'日本語を勉強しています'},{en:\"I'm from the UK\",jp:'私はイギリスから来ました'},\n  {en:'Nice to meet you',jp:'はじめまして'},{en:'Pleased to meet you',jp:'よろしくお願いします'},\n  {en:'Where is the station?',jp:'駅はどこですか？'},{en:'Where is the toilet?',jp:'トイレはどこですか？'},\n  {en:'I like Japanese',jp:'日本語が好きです'},{en:'Do your best!',jp:'がんばって！'},\n  {en:\"I'll do my best\",jp:'がんばります'},{en:'I practise every day',jp:'毎日練習します'},\n  {en:'Delicious!',jp:'おいしい！'},{en:'The bill, please',jp:'お会計をお願いします'},\n  {en:\"I'll take this\",jp:'これをください'},{en:'I want to go to Japan',jp:'日本に行きたいです'},\n  {en:'Good night',jp:'おやすみなさい'},{en:\"It's okay\",jp:'大丈夫です'},\n  {en:'Do you speak English?',jp:'英語が話せますか？'},{en:'I speak a little Japanese',jp:'日本語を少し話せます'},\n  {en:'Please turn right',jp:'右に曲がってください'},{en:'Please turn left',jp:'左に曲がってください'}\n];\n\nlet questions = [], currentIdx = 0, score = 0, answered = false;\n\nfunction shuffle(arr) {\n  const a = arr.slice();\n  for (let i = a.length - 1; i \u003e 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n\nfunction startQuiz() {\n  questions = shuffle(SENTENCES).slice(0, 10);\n  currentIdx = 0; score = 0; answered = false;\n  document.getElementById('quiz-box').style.display = 'block';\n  document.querySelector('.quiz-mode-btns').style.display = 'none';\n  renderQuestion();\n}\n\nfunction renderQuestion() {\n  answered = false;\n  const q = questions[currentIdx];\n  document.getElementById('quiz-progress-bar').style.width = ((currentIdx / 10) * 100) + '%';\n  document.getElementById('quiz-counter').textContent = 'Question ' + (currentIdx + 1) + ' of 10';\n  document.getElementById('quiz-char').textContent = q.en;\n  document.getElementById('quiz-feedback').textContent = '';\n  const wrongs = shuffle(SENTENCES.filter(function(x){ return x.jp !== q.jp; })).slice(0, 3);\n  const options = shuffle([q].concat(wrongs));\n  const grid = document.getElementById('quiz-options');\n  grid.innerHTML = '';\n  options.forEach(function(opt) {\n    const btn = document.createElement('button');\n    btn.className = 'q-opt-btn';\n    btn.textContent = opt.jp;\n    btn.style.cssText = 'font-size:0.95rem;text-align:left;padding:0.7rem 0.8rem;height:auto;white-space:normal;';\n    btn.onclick = function(e){\n      if (e.target === btn) checkAnswer(btn, opt.jp, q);\n    };\n    // sub-label for hearing\n    const hear = document.createElement('span');\n    hear.textContent = ' ▶';\n    hear.style.cssText = 'font-size:0.7rem;opacity:0.6;cursor:pointer;';\n    hear.onclick = function(e){ e.stopPropagation(); speak(opt.jp); };\n    btn.appendChild(hear);\n    grid.appendChild(btn);\n  });\n}\n\nfunction checkAnswer(btn, selected, q) {\n  if (answered) return;\n  answered = true;\n  const isCorrect = selected === q.jp;\n  if (isCorrect) { btn.classList.add('correct'); score++; speak(q.jp); document.getElementById('quiz-feedback').textContent = '✓ Correct!'; }\n  else {\n    btn.classList.add('wrong');\n    document.getElementById('quiz-feedback').textContent = '✗ Wrong';\n    document.querySelectorAll('.q-opt-btn').forEach(function(b){\n      if (b.textContent.replace(' ▶','') === q.jp || b.textContent.startsWith(q.jp)) b.classList.add('correct');\n    });\n    speak(q.jp);\n  }\n  document.querySelectorAll('.q-opt-btn').forEach(function(b){ b.disabled = true; });\n  setTimeout(function(){ currentIdx++; if (currentIdx \u003c 10) { renderQuestion(); } else { showResult(); } }, 1600);\n}\n\nfunction showResult() {\n  const pct = Math.round((score / 10) * 100);\n  const msg = pct === 100 ? '完璧！ Perfect!' : pct \u003e= 80 ? 'すごい！ Excellent!' : pct \u003e= 60 ? 'よくできました！ Good work!' : 'もう一度！ Keep practicing!';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv class=\"quiz-result\"\u003e\u003cdiv class=\"result-score\"\u003e' + score + '/10\u003c/div\u003e\u003cdiv class=\"result-label\"\u003e' + pct + '%\u003c/div\u003e' +\n    '\u003cdiv class=\"result-msg\"\u003e' + msg + '\u003c/div\u003e\u003cbutton class=\"quiz-restart-btn\" onclick=\"resetQuiz()\"\u003eTry Again\u003c/button\u003e\u003c/div\u003e';\n}\n\nfunction resetQuiz() {\n  document.getElementById('quiz-box').style.display = 'none';\n  document.getElementById('quiz-box').innerHTML =\n    '\u003cdiv id=\"quiz-progress-bar-bg\"\u003e\u003cdiv id=\"quiz-progress-bar\"\u003e\u003c/div\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-counter\"\u003eQuestion 1 of 10\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char\" style=\"font-size:1.25rem;line-height:1.5;text-align:center;padding:1rem 0.5rem;min-height:3.5rem\"\u003e?\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-char-hint\" style=\"font-size:0.76rem\"\u003ePick the Japanese translation below\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-options\" style=\"display:grid;grid-template-columns:1fr;gap:0.6rem\"\u003e\u003c/div\u003e' +\n    '\u003cdiv id=\"quiz-feedback\"\u003e\u003c/div\u003e';\n  document.querySelector('.quiz-mode-btns').style.display = 'flex';\n}\n\nfunction speak(text) {\n  if (!('speechSynthesis' in window)) return;\n  window.speechSynthesis.cancel();\n  const u = new SpeechSynthesisUtterance(text);\n  u.lang = 'ja-JP'; u.rate = 0.82;\n  window.speechSynthesis.speak(u);\n}\n\u003c/script\u003e","title":"Sentence Quiz"}]