<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
    <channel>
        <title>Маргарита - Ігри</title>
        <link>http://margo.mozello.shop/gry/</link>
        <description>Маргарита - Ігри</description>
                    <item>
                <title>Написання слова через частини слова</title>
                <link>http://margo.mozello.shop/gry/params/post/5246769/4</link>
                <pubDate>Thu, 30 Apr 2026 12:29:00 +0000</pubDate>
                <description>написання слова через частини слова&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;4&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;


&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;MorphoPlay — Кольорові Морфеми&lt;/title&gt;

&lt;style&gt;
:root{
  --prefix:#ef4444;
  --root:#22c55e;
  --suffix:#3b82f6;
  --ending:#f59e0b;
  --primary:#4f46e5;
}

body{
  margin:0;
  font-family:Arial,sans-serif;
  background:#eef2ff;
  padding:15px;
}

.container{
  max-width:1000px;
  margin:auto;
}

.card{
  background:white;
  border-radius:20px;
  padding:20px;
  margin-bottom:20px;
  box-shadow:0 8px 20px rgba(0,0,0,0.08);
}

h1,h2,h3{
  text-align:center;
}

h1{
  color:var(--primary);
}

label{
  display:block;
  margin-top:10px;
  font-weight:bold;
}

input,textarea{
  width:100%;
  padding:14px;
  margin-top:6px;
  font-size:18px;
  border-radius:12px;
  border:2px solid #cbd5e1;
  box-sizing:border-box;
}

textarea{
  min-height:120px;
}

button{
  width:100%;
  padding:14px;
  margin-top:12px;
  border:none;
  border-radius:14px;
  font-size:20px;
  font-weight:bold;
  cursor:pointer;
}

.main-btn{
  background:var(--primary);
  color:white;
}

.sound-btn{
  background:#f59e0b;
  color:white;
}

.reset-btn{
  background:#ef4444;
  color:white;
}

#taskWord{
  text-align:center;
  font-size:clamp(2rem,8vw,4rem);
  font-weight:bold;
  color:var(--primary);
  margin:15px 0;
}

.row{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:10px;
  margin-top:15px;
}

.slot,.tile{
  min-width:80px;
  min-height:80px;
  padding:10px;
  border-radius:16px;
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:24px;
  font-weight:bold;
  text-align:center;
}

.slot{
  background:#f8fafc;
  border:3px dashed #cbd5e1;
}

.tile{
  color:white;
  border:none;
}

.tile.used{
  opacity:0.35;
  pointer-events:none;
}

.prefix{background:var(--prefix);}
.root{background:var(--root);}
.suffix{background:var(--suffix);}
.ending{background:var(--ending);}

.legend{
  display:grid;
  grid-template-columns:repeat(2,1fr);
  gap:8px;
  margin-top:12px;
}

.legend div{
  color:white;
  padding:8px;
  border-radius:10px;
  text-align:center;
  font-weight:bold;
}

#status,#stars{
  text-align:center;
  font-size:28px;
  margin-top:15px;
}
&lt;/style&gt;



&lt;div class=&quot;container&quot;&gt;

&lt;div class=&quot;card&quot;&gt;
&lt;h1&gt;🧠 MorphoPlay&lt;/h1&gt;

&lt;label&gt;Слово:&lt;/label&gt;
&lt;input id=&quot;wordInput&quot; placeholder=&quot;переписка&quot; fdprocessedid=&quot;5tjroc&quot;&gt;

&lt;label&gt;Морфеми (кожен рядок: частина|тип)&lt;/label&gt;
&lt;textarea id=&quot;morphemeInput&quot;&gt;пере|prefix
пис|root
к|suffix
а|ending&lt;/textarea&gt;

&lt;button class=&quot;main-btn&quot; onclick=&quot;createGame()&quot; fdprocessedid=&quot;fr1t7d&quot;&gt;Створити гру&lt;/button&gt;

&lt;div class=&quot;legend&quot;&gt;
&lt;div style=&quot;background:#ef4444;&quot;&gt;🔴 Префікс&lt;/div&gt;
&lt;div style=&quot;background:#22c55e;&quot;&gt;🟢 Корінь&lt;/div&gt;
&lt;div style=&quot;background:#3b82f6;&quot;&gt;🔵 Суфікс&lt;/div&gt;
&lt;div style=&quot;background:#f59e0b;&quot;&gt;🟠 Закінчення&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;card&quot;&gt;
&lt;h2&gt;Збери слово&lt;/h2&gt;

&lt;div id=&quot;taskWord&quot;&gt;—&lt;/div&gt;

&lt;div class=&quot;row&quot; id=&quot;answerArea&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;row&quot; id=&quot;tileArea&quot;&gt;&lt;/div&gt;

&lt;button class=&quot;sound-btn&quot; onclick=&quot;speakWord()&quot; fdprocessedid=&quot;jhg6of&quot;&gt;🔊 Озвучити&lt;/button&gt;
&lt;button class=&quot;reset-btn&quot; onclick=&quot;resetGame()&quot; fdprocessedid=&quot;9c44xk&quot;&gt;🔄 Очистити&lt;/button&gt;

&lt;div id=&quot;status&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;stars&quot;&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
let targetWord=&quot;&quot;;
let morphemes=[];
let selected=[];

// ---------- CREATE ----------
function createGame(){
  targetWord=document.getElementById(&quot;wordInput&quot;).value.trim().toLowerCase();
  const raw=document.getElementById(&quot;morphemeInput&quot;).value.trim();

  if(!targetWord){
    alert(&quot;Введіть слово&quot;);
    return;
  }

  if(!raw){
    alert(&quot;Введіть морфеми&quot;);
    return;
  }

  morphemes=[];

  const lines=raw.split(&quot;\n&quot;);

  for(let i=0;i&lt;lines.length;i++){
    let line=lines[i].trim();

    if(!line) continue;

    let parts=line.split(&quot;|&quot;);

    let text=(parts[0] || &quot;&quot;).trim().toLowerCase();
    let type=(parts[1] || &quot;root&quot;).trim().toLowerCase();

    if(text){
      morphemes.push({
        text:text,
        type:type
      });
    }
  }

  if(morphemes.length===0){
    alert(&quot;Помилка морфем&quot;);
    return;
  }

  selected=[];

  document.getElementById(&quot;taskWord&quot;).textContent=targetWord.toUpperCase();
  document.getElementById(&quot;status&quot;).textContent=&quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent=&quot;&quot;;

  renderAnswer();
  renderTiles();
}

// ---------- ANSWER ----------
function renderAnswer(){
  const area=document.getElementById(&quot;answerArea&quot;);
  area.innerHTML=&quot;&quot;;

  for(let i=0;i&lt;morphemes.length;i++){
    let slot=document.createElement(&quot;div&quot;);
    slot.className=&quot;slot&quot;;

    if(selected[i]){
      slot.textContent=selected[i].text;
    }

    area.appendChild(slot);
  }
}

// ---------- SHUFFLE ----------
function shuffle(array){
  let arr=[...array];

  for(let i=arr.length-1;i&gt;0;i--){
    let j=Math.floor(Math.random()*(i+1));
    [arr[i],arr[j]]=[arr[j],arr[i]];
  }

  if(arr.length&gt;1){
    let original=array.map(x=&gt;x.text).join(&quot;&quot;);
    let shuffled=arr.map(x=&gt;x.text).join(&quot;&quot;);

    if(original===shuffled){
      [arr[0],arr[1]]=[arr[1],arr[0]];
    }
  }

  return arr;
}

// ---------- TILES ----------
function renderTiles(){
  const area=document.getElementById(&quot;tileArea&quot;);
  area.innerHTML=&quot;&quot;;

  let shuffled=shuffle(morphemes);

  shuffled.forEach(item=&gt;{
    let tile=document.createElement(&quot;button&quot;);

    tile.className=&quot;tile &quot; + item.type;
    tile.textContent=item.text;

    tile.onclick=function(){
      if(selected.length&gt;=morphemes.length) return;

      selected.push(item);

      tile.classList.add(&quot;used&quot;);

      speak(item.text);

      renderAnswer();
      checkAnswer();
    };

    area.appendChild(tile);
  });
}

// ---------- CHECK ----------
function checkAnswer(){
  if(selected.length!==morphemes.length) return;

  let result=selected.map(x=&gt;x.text).join(&quot;&quot;);

  if(result===targetWord){
    document.getElementById(&quot;status&quot;).textContent=&quot;🎉 Молодець!&quot;;
    document.getElementById(&quot;stars&quot;).textContent=&quot;⭐ ⭐ ⭐&quot;;

    speakWord();
  }else{
    document.getElementById(&quot;status&quot;).textContent=&quot;🙂 Спробуй ще раз&quot;;
  }
}

// ---------- RESET ----------
function resetGame(){
  selected=[];

  document.getElementById(&quot;status&quot;).textContent=&quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent=&quot;&quot;;

  renderAnswer();
  renderTiles();
}

// ---------- SOUND ----------
function getVoice(){
  if(!window.speechSynthesis) return null;

  let voices=speechSynthesis.getVoices();

  return (
    voices.find(v=&gt;v.lang===&quot;uk-UA&quot;) ||
    voices.find(v=&gt;v.lang.startsWith(&quot;uk&quot;)) ||
    voices[0] ||
    null
  );
}

function speak(text){
  if(!window.speechSynthesis) return;

  speechSynthesis.cancel();

  let utterance=new SpeechSynthesisUtterance(text);

  let voice=getVoice();

  if(voice){
    utterance.voice=voice;
    utterance.lang=voice.lang;
  }else{
    utterance.lang=&quot;uk-UA&quot;;
  }

  utterance.rate=0.65;
  utterance.pitch=1;

  speechSynthesis.speak(utterance);
}

function speakWord(){
  if(targetWord){
    speak(targetWord);
  }
}

document.addEventListener(&quot;click&quot;, ()=&gt;{
  if(window.speechSynthesis){
    speechSynthesis.resume();
  }
},{once:true});

document.addEventListener(&quot;touchstart&quot;, ()=&gt;{
  if(window.speechSynthesis){
    speechSynthesis.resume();
  }
},{once:true});
&lt;/script&gt;</description>
            </item>
                    <item>
                <title>🎓 СкладоГра3</title>
                <link>http://margo.mozello.shop/gry/params/post/5246122/skladogra3</link>
                <pubDate>Wed, 29 Apr 2026 10:58:00 +0000</pubDate>
                <description>оооооооооооооооооооооо&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;3&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;


  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;&gt;
  &lt;meta name=&quot;theme-color&quot; content=&quot;#4f46e5&quot;&gt;
  &lt;title&gt;СкладоГра — Навчання читанню&lt;/title&gt;

  &lt;style&gt;
    :root {
      --primary: #4f46e5;
      --accent: #f59e0b;
      --danger: #ef4444;
      --text: #1e293b;
      --radius: 20px;
      --shadow: 0 10px 25px rgba(0,0,0,0.08);
      --button-size: clamp(64px, 18vw, 110px);
    }

    * {
      box-sizing: border-box;
      -webkit-tap-highlight-color: transparent;
    }

    body {
      margin: 0;
      font-family: Arial, sans-serif;
      background: linear-gradient(180deg, #eef2ff, #f8fafc);
      color: var(--text);
      overflow-x: hidden;
    }

    .app {
      max-width: 900px;
      margin: 0 auto;
      padding: 16px;
    }

    .card {
      background: white;
      border-radius: var(--radius);
      padding: 18px;
      margin-bottom: 20px;
      box-shadow: var(--shadow);
    }

    h1, h2 {
      text-align: center;
      margin-top: 0;
    }

    h1 {
      color: var(--primary);
    }

    .mom-controls {
      display: flex;
      flex-direction: column;
      gap: 12px;
    }

    input {
      width: 100%;
      padding: 16px;
      font-size: 1.2rem;
      border-radius: 14px;
      border: 2px solid #cbd5e1;
    }

    button {
      border: none;
      border-radius: 16px;
      padding: 14px;
      font-size: 1.1rem;
      font-weight: bold;
      cursor: pointer;
      min-height: 56px;
    }

    .primary-btn { background: var(--primary); color: white; }
    .accent-btn { background: var(--accent); color: white; }
    .danger-btn { background: var(--danger); color: white; }

    .emoji {
      text-align: center;
      font-size: clamp(3rem, 12vw, 6rem);
    }

    #taskWord {
      text-align: center;
      font-size: clamp(2rem, 8vw, 4rem);
      font-weight: bold;
      color: var(--primary);
      margin: 10px 0 18px;
      word-break: break-word;
    }

    .syllables, .answer {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      justify-content: center;
      margin-top: 16px;
    }

    .tile, .slot {
      min-width: var(--button-size);
      min-height: var(--button-size);
      padding: 10px;
      border-radius: 18px;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: clamp(1rem, 3vw, 1.4rem);
      font-weight: bold;
      text-align: center;
      user-select: none;
    }

    .tile {
      background: #dbeafe;
      border: 3px solid #93c5fd;
    }

    .tile.used {
      opacity: 0.35;
      pointer-events: none;
    }

    .slot {
      background: #f1f5f9;
      border: 3px dashed #cbd5e1;
    }

    .controls {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
      margin-top: 16px;
    }

    .status, .stars {
      text-align: center;
      margin-top: 14px;
      font-weight: bold;
      min-height: 28px;
    }

    .description {
      line-height: 1.7;
      font-size: 1rem;
    }

    ul {
      padding-left: 20px;
    }
  &lt;/style&gt;



&lt;div class=&quot;app&quot;&gt;

  &lt;!-- МАМА --&gt;
  &lt;div class=&quot;card&quot;&gt;
    &lt;h1&gt;🎓 СкладоГра&lt;/h1&gt;

    &lt;div class=&quot;mom-controls&quot;&gt;
      &lt;label&gt;&lt;b&gt;Введіть слово:&lt;/b&gt;&lt;/label&gt;
      &lt;input id=&quot;wordInput&quot; type=&quot;text&quot; placeholder=&quot;Наприклад: машина&quot;&gt;

      &lt;label&gt;&lt;b&gt;Склади (можна вручну):&lt;/b&gt;&lt;/label&gt;
      &lt;input id=&quot;manualSyllables&quot; type=&quot;text&quot; placeholder=&quot;ма-ши-на&quot;&gt;

      &lt;button class=&quot;primary-btn&quot; onclick=&quot;createGame()&quot;&gt;Створити гру&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- ДИТИНА --&gt;
  &lt;div class=&quot;card&quot;&gt;
    &lt;div class=&quot;emoji&quot; id=&quot;emojiDisplay&quot;&gt;🧩&lt;/div&gt;

    &lt;h2&gt;Склади слово&lt;/h2&gt;

    &lt;div id=&quot;taskWord&quot;&gt;—&lt;/div&gt;

    &lt;div class=&quot;answer&quot; id=&quot;answerArea&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;syllables&quot; id=&quot;syllableArea&quot;&gt;&lt;/div&gt;

    &lt;div class=&quot;controls&quot;&gt;
      &lt;button class=&quot;accent-btn&quot; onclick=&quot;speakWord()&quot;&gt;🔊 Озвучити&lt;/button&gt;
      &lt;button class=&quot;danger-btn&quot; onclick=&quot;resetAnswer()&quot;&gt;🔄 Очистити&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;status&quot; id=&quot;status&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;stars&quot; id=&quot;stars&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- ІНСТРУКЦІЯ --&gt;
  &lt;div class=&quot;card description&quot;&gt;
    &lt;h2&gt;📘 Опис гри&lt;/h2&gt;
    &lt;p&gt;
      Мама вводить слово, а дитина складає його з переплутаних складів.
      Гра працює на смартфонах, планшетах і ПК.
    &lt;/p&gt;

    &lt;h2&gt;👩 Інструкція для мами&lt;/h2&gt;
    &lt;ul&gt;
      &lt;li&gt;Введіть слово.&lt;/li&gt;
      &lt;li&gt;За потреби виправте поділ на склади вручну.&lt;/li&gt;
      &lt;li&gt;Натисніть “Створити гру”.&lt;/li&gt;
      &lt;li&gt;Дитина бачить слово-завдання та обирає склади в правильному порядку.&lt;/li&gt;
      &lt;li&gt;Кнопка “Озвучити” читає слово або склади.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
let targetWord = &quot;&quot;;
let syllables = [];
let selected = [];
let voicesReady = false;

const emojiMap = {
  &quot;мама&quot;: &quot;👩&quot;,
  &quot;тато&quot;: &quot;👨&quot;,
  &quot;кіт&quot;: &quot;🐱&quot;,
  &quot;собака&quot;: &quot;🐶&quot;,
  &quot;машина&quot;: &quot;🚗&quot;,
  &quot;яблуко&quot;: &quot;🍎&quot;,
  &quot;сонце&quot;: &quot;☀️&quot;
};

// -------- ПОДІЛ НА СКЛАДИ --------
function splitIntoSyllables(word) {
  word = word.toLowerCase().replace(/\s+/g, &quot;&quot;);
  const vowels = &quot;аеєиіїоуюя&quot;;

  if (word.length &lt;= 2) return [word];

  let vowelPositions = [];

  for (let i = 0; i &lt; word.length; i++) {
    if (vowels.includes(word[i])) vowelPositions.push(i);
  }

  if (vowelPositions.length &lt;= 1) return [word];

  let result = [];
  let start = 0;

  for (let i = 0; i &lt; vowelPositions.length - 1; i++) {
    const current = vowelPositions[i];
    const next = vowelPositions[i + 1];
    const between = next - current - 1;

    let splitPos = between &lt;= 1 ? current + 1 : current + 2;

    result.push(word.slice(start, splitPos));
    start = splitPos;
  }

  result.push(word.slice(start));

  return result.filter(Boolean);
}

// -------- СТВОРЕННЯ ГРИ --------
function createGame() {
  targetWord = document.getElementById(&quot;wordInput&quot;).value.trim().toLowerCase();
  if (!targetWord) return;

  const manual = document.getElementById(&quot;manualSyllables&quot;).value.trim();

  if (manual) {
    syllables = manual.split(&quot;-&quot;).map(s =&gt; s.trim().toLowerCase()).filter(Boolean);
  } else {
    syllables = splitIntoSyllables(targetWord);
    document.getElementById(&quot;manualSyllables&quot;).value = syllables.join(&quot;-&quot;);
  }

  selected = [];

  document.getElementById(&quot;taskWord&quot;).textContent = targetWord.toUpperCase();

  renderAnswerSlots();
  renderSyllables();

  document.getElementById(&quot;status&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;emojiDisplay&quot;).textContent = emojiMap[targetWord] || &quot;🧩&quot;;

  unlockSpeech();
  speakWord();
}

// -------- СЛОТИ --------
function renderAnswerSlots() {
  const area = document.getElementById(&quot;answerArea&quot;);
  area.innerHTML = &quot;&quot;;

  for (let i = 0; i &lt; syllables.length; i++) {
    const slot = document.createElement(&quot;div&quot;);
    slot.className = &quot;slot&quot;;
    slot.textContent = selected[i] || &quot;&quot;;
    area.appendChild(slot);
  }
}

// -------- ПЕРЕМІШАНІ СКЛАДИ --------
function renderSyllables() {
  const area = document.getElementById(&quot;syllableArea&quot;);
  area.innerHTML = &quot;&quot;;

  let shuffled = [...syllables];

  for (let i = shuffled.length - 1; i &gt; 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
  }

  if (shuffled.length &gt; 1 &amp;&amp; shuffled.join(&quot;&quot;) === syllables.join(&quot;&quot;)) {
    [shuffled[0], shuffled[1]] = [shuffled[1], shuffled[0]];
  }

  shuffled.forEach(syllable =&gt; {
    const btn = document.createElement(&quot;button&quot;);
    btn.className = &quot;tile&quot;;
    btn.textContent = syllable;

    btn.onclick = () =&gt; {
      if (selected.length &gt;= syllables.length) return;

      selected.push(syllable);
      btn.classList.add(&quot;used&quot;);

      speakSyllable(syllable);

      renderAnswerSlots();
      checkAnswer();
    };

    area.appendChild(btn);
  });
}

// -------- ПЕРЕВІРКА --------
function checkAnswer() {
  if (selected.length !== syllables.length) return;

  const formed = selected.join(&quot;&quot;);

  if (formed === targetWord) {
    document.getElementById(&quot;status&quot;).textContent = &quot;🎉 Молодець!&quot;;
    document.getElementById(&quot;stars&quot;).textContent = &quot;⭐ ⭐ ⭐&quot;;
    speakWord();

    if (navigator.vibrate) navigator.vibrate([150, 70, 150]);
  } else {
    document.getElementById(&quot;status&quot;).textContent = &quot;🙂 Спробуй ще раз&quot;;
  }
}

// -------- RESET --------
function resetAnswer() {
  selected = [];
  renderAnswerSlots();
  renderSyllables();
  document.getElementById(&quot;status&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent = &quot;&quot;;
}

// -------- ОЗВУЧЕННЯ --------
function loadVoices() {
  return new Promise((resolve) =&gt; {
    let voices = speechSynthesis.getVoices();

    if (voices.length) {
      voicesReady = true;
      resolve(voices);
      return;
    }

    speechSynthesis.onvoiceschanged = () =&gt; {
      voices = speechSynthesis.getVoices();
      voicesReady = true;
      resolve(voices);
    };

    setTimeout(() =&gt; {
      resolve(speechSynthesis.getVoices());
    }, 1200);
  });
}

function getBestVoice() {
  const voices = speechSynthesis.getVoices();

  return (
    voices.find(v =&gt; v.lang === &quot;uk-UA&quot;) ||
    voices.find(v =&gt; v.lang.toLowerCase().startsWith(&quot;uk&quot;)) ||
    voices.find(v =&gt; v.lang.toLowerCase().startsWith(&quot;ru&quot;)) ||
    voices.find(v =&gt; v.name.toLowerCase().includes(&quot;google&quot;)) ||
    voices[0] ||
    null
  );
}

function fallbackSpeakWord() {
  if (!syllables.length) return;

  let delay = 0;

  syllables.forEach(part =&gt; {
    setTimeout(() =&gt; {
      const u = new SpeechSynthesisUtterance(part);
      u.lang = &quot;uk-UA&quot;;
      u.rate = 0.55;
      u.pitch = 1;
      speechSynthesis.speak(u);
    }, delay);

    delay += 900;
  });
}

async function speakText(text, isWord = false) {
  if (!(&quot;speechSynthesis&quot; in window)) return;

  await loadVoices();

  speechSynthesis.cancel();

  const voice = getBestVoice();

  if (!voice) {
    if (isWord) fallbackSpeakWord();
    return;
  }

  speechSynthesis.resume();

  const utterance = new SpeechSynthesisUtterance(text);

  utterance.voice = voice;
  utterance.lang = voice.lang || &quot;uk-UA&quot;;
  utterance.rate = isWord ? 0.65 : 0.55;
  utterance.pitch = 1;
  utterance.volume = 1;

  utterance.onerror = () =&gt; {
    if (isWord) fallbackSpeakWord();
  };

  speechSynthesis.speak(utterance);
}

function speakSyllable(syllable) {
  speakText(syllable, false);
}

function speakWord() {
  if (!targetWord) return;

  if (!voicesReady || !getBestVoice()) {
    fallbackSpeakWord();
  } else {
    speakText(targetWord, true);
  }
}

function unlockSpeech() {
  if (!(&quot;speechSynthesis&quot; in window)) return;

  speechSynthesis.resume();

  const unlock = new SpeechSynthesisUtterance(&quot; &quot;);
  unlock.volume = 0;
  speechSynthesis.speak(unlock);

  loadVoices();
}

document.addEventListener(&quot;touchstart&quot;, unlockSpeech, { once: true });
document.addEventListener(&quot;click&quot;, unlockSpeech, { once: true });

window.addEventListener(&quot;load&quot;, () =&gt; {
  loadVoices();
});
&lt;/script&gt;</description>
            </item>
                    <item>
                <title>🎓 СкладоГра 2</title>
                <link>http://margo.mozello.shop/gry/params/post/5246106/skladogra-2</link>
                <pubDate>Wed, 29 Apr 2026 10:40:00 +0000</pubDate>
                <description>дддддддддддддддддддддддд&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;2&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;


  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;&gt;
  &lt;meta name=&quot;theme-color&quot; content=&quot;#4f46e5&quot;&gt;
  &lt;title&gt;СкладоГра — Навчання читанню&lt;/title&gt;

  &lt;style&gt;
    :root {
      --primary: #4f46e5;
      --accent: #f59e0b;
      --danger: #ef4444;
      --text: #1e293b;
      --radius: 20px;
      --shadow: 0 10px 25px rgba(0,0,0,0.08);
      --button-size: clamp(64px, 18vw, 110px);
    }

    * {
      box-sizing: border-box;
      -webkit-tap-highlight-color: transparent;
    }

    body {
      margin: 0;
      font-family: Arial, sans-serif;
      background: linear-gradient(180deg, #eef2ff, #f8fafc);
      color: var(--text);
    }

    .app {
      max-width: 900px;
      margin: 0 auto;
      padding: 16px;
    }

    .card {
      background: white;
      border-radius: var(--radius);
      padding: 18px;
      margin-bottom: 20px;
      box-shadow: var(--shadow);
    }

    h1, h2 {
      text-align: center;
    }

    h1 {
      color: var(--primary);
    }

    .mom-controls {
      display: flex;
      flex-direction: column;
      gap: 12px;
    }

    input {
      width: 100%;
      padding: 16px;
      font-size: 1.2rem;
      border-radius: 14px;
      border: 2px solid #cbd5e1;
    }

    button {
      border: none;
      border-radius: 16px;
      padding: 14px;
      font-size: 1.1rem;
      font-weight: bold;
      cursor: pointer;
      min-height: 56px;
    }

    .primary-btn { background: var(--primary); color: white; }
    .accent-btn { background: var(--accent); color: white; }
    .danger-btn { background: var(--danger); color: white; }

    .emoji {
      text-align: center;
      font-size: clamp(3rem, 12vw, 6rem);
    }

    #taskWord {
      text-align: center;
      font-size: clamp(2rem, 8vw, 4rem);
      font-weight: bold;
      color: var(--primary);
      margin: 10px 0;
      word-break: break-word;
    }

    #taskSyllables {
      text-align: center;
      font-size: clamp(1rem, 4vw, 1.6rem);
      color: #64748b;
      margin-bottom: 14px;
    }

    .syllables, .answer {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      justify-content: center;
      margin-top: 16px;
    }

    .tile, .slot {
      min-width: var(--button-size);
      min-height: var(--button-size);
      padding: 10px;
      border-radius: 18px;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: clamp(1rem, 3vw, 1.4rem);
      font-weight: bold;
      text-align: center;
    }

    .tile {
      background: #dbeafe;
      border: 3px solid #93c5fd;
    }

    .tile.used {
      opacity: 0.35;
      pointer-events: none;
    }

    .slot {
      background: #f1f5f9;
      border: 3px dashed #cbd5e1;
    }

    .controls {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
      margin-top: 16px;
    }

    .status, .stars {
      text-align: center;
      margin-top: 14px;
      font-weight: bold;
    }
  &lt;/style&gt;



&lt;div class=&quot;app&quot;&gt;

  &lt;div class=&quot;card&quot;&gt;
    &lt;h1&gt;🎓 СкладоГра&lt;/h1&gt;

    &lt;div class=&quot;mom-controls&quot;&gt;
      &lt;label&gt;&lt;b&gt;Введіть слово:&lt;/b&gt;&lt;/label&gt;
      &lt;input id=&quot;wordInput&quot; type=&quot;text&quot; placeholder=&quot;Наприклад: машина&quot;&gt;

      &lt;label&gt;&lt;b&gt;Склади (можна вручну):&lt;/b&gt;&lt;/label&gt;
      &lt;input id=&quot;manualSyllables&quot; type=&quot;text&quot; placeholder=&quot;ма-ши-на&quot;&gt;

      &lt;button class=&quot;primary-btn&quot; onclick=&quot;createGame()&quot;&gt;Створити гру&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;card&quot;&gt;
    &lt;div class=&quot;emoji&quot; id=&quot;emojiDisplay&quot;&gt;🧩&lt;/div&gt;

    &lt;h2&gt;Склади слово&lt;/h2&gt;

    &lt;div id=&quot;taskWord&quot;&gt;—&lt;/div&gt;
    &lt;div id=&quot;taskSyllables&quot;&gt;&lt;/div&gt;

    &lt;div class=&quot;answer&quot; id=&quot;answerArea&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;syllables&quot; id=&quot;syllableArea&quot;&gt;&lt;/div&gt;

    &lt;div class=&quot;controls&quot;&gt;
      &lt;button class=&quot;accent-btn&quot; onclick=&quot;speakWord()&quot;&gt;🔊 Озвучити&lt;/button&gt;
      &lt;button class=&quot;danger-btn&quot; onclick=&quot;resetAnswer()&quot;&gt;🔄 Очистити&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;status&quot; id=&quot;status&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;stars&quot; id=&quot;stars&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
let targetWord = &quot;&quot;;
let syllables = [];
let selected = [];

const emojiMap = {
  &quot;мама&quot;: &quot;👩&quot;,
  &quot;тато&quot;: &quot;👨&quot;,
  &quot;кіт&quot;: &quot;🐱&quot;,
  &quot;собака&quot;: &quot;🐶&quot;,
  &quot;машина&quot;: &quot;🚗&quot;,
  &quot;яблуко&quot;: &quot;🍎&quot;,
  &quot;сонце&quot;: &quot;☀️&quot;
};

// КРАЩИЙ ПОДІЛ НА СКЛАДИ
function splitIntoSyllables(word) {
  word = word.toLowerCase().replace(/\s+/g, &quot;&quot;);
  const vowels = &quot;аеєиіїоуюя&quot;;

  if (word.length &lt;= 2) return [word];

  let vowelPositions = [];

  for (let i = 0; i &lt; word.length; i++) {
    if (vowels.includes(word[i])) vowelPositions.push(i);
  }

  if (vowelPositions.length &lt;= 1) return [word];

  let result = [];
  let start = 0;

  for (let i = 0; i &lt; vowelPositions.length - 1; i++) {
    const current = vowelPositions[i];
    const next = vowelPositions[i + 1];
    const between = next - current - 1;

    let splitPos;

    if (between &lt;= 1) splitPos = current + 1;
    else splitPos = current + 2;

    result.push(word.slice(start, splitPos));
    start = splitPos;
  }

  result.push(word.slice(start));

  return result.filter(Boolean);
}

function shuffleArray(arr) {
  return [...arr].sort(() =&gt; Math.random() - 0.5);
}

function createGame() {
  targetWord = document.getElementById(&quot;wordInput&quot;).value.trim().toLowerCase();
  if (!targetWord) return;

  const manual = document.getElementById(&quot;manualSyllables&quot;).value.trim();

  if (manual) {
    syllables = manual.split(&quot;-&quot;).map(s =&gt; s.trim().toLowerCase()).filter(Boolean);
  } else {
    syllables = splitIntoSyllables(targetWord);
    document.getElementById(&quot;manualSyllables&quot;).value = syllables.join(&quot;-&quot;);
  }

  selected = [];

  document.getElementById(&quot;taskWord&quot;).textContent = targetWord.toUpperCase();
  document.getElementById(&quot;taskSyllables&quot;).textContent = syllables.join(&quot; • &quot;).toUpperCase();

  renderAnswerSlots();
  renderSyllables();

  document.getElementById(&quot;status&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;emojiDisplay&quot;).textContent = emojiMap[targetWord] || &quot;🧩&quot;;

  unlockSpeech();
  speakWord();
}

function renderAnswerSlots() {
  const area = document.getElementById(&quot;answerArea&quot;);
  area.innerHTML = &quot;&quot;;

  for (let i = 0; i &lt; syllables.length; i++) {
    const slot = document.createElement(&quot;div&quot;);
    slot.className = &quot;slot&quot;;
    slot.textContent = selected[i] || &quot;&quot;;
    area.appendChild(slot);
  }
}

function renderSyllables() {
  const area = document.getElementById(&quot;syllableArea&quot;);
  area.innerHTML = &quot;&quot;;

  shuffleArray(syllables).forEach(syllable =&gt; {
    const btn = document.createElement(&quot;button&quot;);
    btn.className = &quot;tile&quot;;
    btn.textContent = syllable;

    btn.onclick = () =&gt; {
      selected.push(syllable);
      btn.classList.add(&quot;used&quot;);

      speakText(syllable);

      renderAnswerSlots();
      checkAnswer();
    };

    area.appendChild(btn);
  });
}

function checkAnswer() {
  if (selected.length !== syllables.length) return;

  const formed = selected.join(&quot;&quot;);

  if (formed === targetWord) {
    document.getElementById(&quot;status&quot;).textContent = &quot;🎉 Молодець!&quot;;
    document.getElementById(&quot;stars&quot;).textContent = &quot;⭐ ⭐ ⭐&quot;;

    speakWord();

    if (navigator.vibrate) navigator.vibrate([150, 70, 150]);
  } else {
    document.getElementById(&quot;status&quot;).textContent = &quot;🙂 Спробуй ще раз&quot;;
  }
}

function resetAnswer() {
  selected = [];
  renderAnswerSlots();
  renderSyllables();
  document.getElementById(&quot;status&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent = &quot;&quot;;
}

// ---------- НАДІЙНА УКРАЇНСЬКА ОЗВУЧКА ----------
function getBestVoice() {
  const voices = speechSynthesis.getVoices();

  return (
    voices.find(v =&gt; v.lang === &quot;uk-UA&quot;) ||
    voices.find(v =&gt; v.lang.toLowerCase().startsWith(&quot;uk&quot;)) ||
    voices.find(v =&gt; v.name.toLowerCase().includes(&quot;ukrain&quot;)) ||
    voices.find(v =&gt; v.name.toLowerCase().includes(&quot;google&quot;)) ||
    null
  );
}

function speakText(text) {
  if (!(&quot;speechSynthesis&quot; in window)) return;

  speechSynthesis.cancel();

  const utterance = new SpeechSynthesisUtterance(text);
  const voice = getBestVoice();

  if (voice) {
    utterance.voice = voice;
    utterance.lang = voice.lang;
  } else {
    utterance.lang = &quot;uk-UA&quot;;
  }

  utterance.rate = 0.7;
  utterance.pitch = 1;
  utterance.volume = 1;

  speechSynthesis.speak(utterance);
}

function speakWord() {
  if (!targetWord) return;

  if (!getBestVoice()) {
    // fallback складами
    speakText(syllables.join(&quot; ... &quot;));
  } else {
    speakText(targetWord);
  }
}

function unlockSpeech() {
  speechSynthesis.resume();
  speechSynthesis.getVoices();
}

window.speechSynthesis.onvoiceschanged = () =&gt; {
  speechSynthesis.getVoices();
};

document.addEventListener(&quot;click&quot;, unlockSpeech, { once: true });
document.addEventListener(&quot;touchstart&quot;, unlockSpeech, { once: true });
&lt;/script&gt;</description>
            </item>
                    <item>
                <title>🎓 СкладоГра</title>
                <link>http://margo.mozello.shop/gry/params/post/5245820/skladogra</link>
                <pubDate>Tue, 28 Apr 2026 21:47:00 +0000</pubDate>
                <description>лллллллллллллллллл&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;1&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;h2 style=&quot;font-style: normal;&quot; class=&quot;moze-center&quot;&gt;📘 Опис гри&lt;/h2&gt;&lt;p style=&quot;font-weight: 400; font-style: normal;&quot; class=&quot;moze-start&quot;&gt;“СкладоГра” — це мобільна навчальна гра для дітей 3–6 років, які ще не читають або лише починають вивчати склади. Дитина бачить частини слова (склади) та натискає їх у правильному порядку, щоб скласти слово.&lt;/p&gt;&lt;h2 style=&quot;font-style: normal;&quot; class=&quot;moze-center&quot;&gt;👩 Інструкція для мами&lt;/h2&gt;&lt;ul style=&quot;text-align: start; font-weight: 400; font-style: normal&quot;&gt;&lt;li&gt;Введіть просте слово українською мовою (наприклад: мама, кіт, машина).&lt;/li&gt;&lt;li&gt;Натисніть “Створити гру”.&lt;/li&gt;&lt;li&gt;Дайте дитині телефон або планшет.&lt;/li&gt;&lt;li&gt;Дитина натискає склади по черзі.&lt;/li&gt;&lt;li&gt;Після правильно складеного слова гра покаже успіх ⭐&lt;/li&gt;&lt;li&gt;Використовуйте кнопку “Озвучити”, щоб дитина чула слово.&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;font-weight: 400; font-style: normal;&quot; class=&quot;moze-start&quot;&gt;&lt;b&gt;Поради:&amp;nbsp;&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;font-weight: 400; font-style: normal;&quot; class=&quot;moze-start&quot;&gt;&amp;nbsp;1.&lt;/p&gt;&lt;p style=&quot;font-weight: 400; font-style: normal;&quot; class=&quot;moze-start&quot;&gt;Починайте з коротких слів із 2 складів.&lt;/p&gt;&lt;p style=&quot;font-weight: 400; font-style: normal;&quot; class=&quot;moze-start&quot;&gt;&amp;nbsp;2&lt;/p&gt;&lt;p style=&quot;font-weight: 400; font-style: normal;&quot; class=&quot;moze-start&quot;&gt;Якщо поділ на склади видався Вам некоректним -- напишіть правильний варіант вручну&lt;/p&gt;

&lt;br&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;


  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;&gt;
  &lt;meta name=&quot;theme-color&quot; content=&quot;#4f46e5&quot;&gt;
  &lt;title&gt;СкладоГра — Навчання читанню&lt;/title&gt;
  &lt;style&gt;
    :root {
      --bg: #f8fafc;
      --card: #ffffff;
      --primary: #4f46e5;
      --accent: #f59e0b;
      --danger: #ef4444;
      --text: #1e293b;
      --radius: 20px;
      --shadow: 0 10px 25px rgba(0,0,0,0.08);
      --font-big: clamp(1.2rem, 4vw, 2rem);
      --font-medium: clamp(1rem, 3vw, 1.4rem);
      --button-size: clamp(64px, 18vw, 110px);
    }

    * {
      box-sizing: border-box;
      -webkit-tap-highlight-color: transparent;
    }

    body {
      margin: 0;
      font-family: Arial, sans-serif;
      background: linear-gradient(180deg, #eef2ff, #f8fafc);
      color: var(--text);
      overflow-x: hidden;
    }

    .app {
      max-width: 900px;
      margin: 0 auto;
      padding: 16px;
    }

    .card {
      background: white;
      border-radius: var(--radius);
      padding: 18px;
      margin-bottom: 20px;
      box-shadow: var(--shadow);
    }

    h1, h2 {
      text-align: center;
    }

    h1 {
      color: var(--primary);
    }

    .mom-controls {
      display: flex;
      flex-direction: column;
      gap: 12px;
    }

    input {
      width: 100%;
      padding: 16px;
      font-size: 1.2rem;
      border-radius: 14px;
      border: 2px solid #cbd5e1;
    }

    button {
      border: none;
      border-radius: 16px;
      padding: 14px;
      font-size: 1.1rem;
      font-weight: bold;
      cursor: pointer;
      min-height: 56px;
    }

    .primary-btn {
      background: var(--primary);
      color: white;
    }

    .accent-btn {
      background: var(--accent);
      color: white;
    }

    .danger-btn {
      background: var(--danger);
      color: white;
    }

    .syllables, .answer {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      justify-content: center;
      margin-top: 16px;
    }

    .tile, .slot {
      min-width: var(--button-size);
      min-height: var(--button-size);
      padding: 10px;
      border-radius: 18px;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: var(--font-medium);
      font-weight: bold;
      text-align: center;
    }

    .tile {
      background: #dbeafe;
      border: 3px solid #93c5fd;
    }

    .tile.used {
      opacity: 0.35;
      pointer-events: none;
    }

    .slot {
      background: #f1f5f9;
      border: 3px dashed #cbd5e1;
    }

    .controls {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
      margin-top: 16px;
    }

    .status, .stars {
      text-align: center;
      margin-top: 14px;
      font-weight: bold;
    }

    .emoji {
      text-align: center;
      font-size: clamp(3rem, 12vw, 6rem);
    }

    .manual-syllables {
      margin-top: 10px;
    }

    .hint {
      font-size: 0.9rem;
      color: #475569;
    }
  &lt;/style&gt;


&lt;div class=&quot;app&quot;&gt;

  &lt;div class=&quot;card&quot;&gt;
    &lt;h1&gt;🎓 СкладоГра&lt;/h1&gt;

    &lt;div class=&quot;mom-controls&quot;&gt;
      &lt;label&gt;&lt;b&gt;Введіть слово:&lt;/b&gt;&lt;/label&gt;
      &lt;input id=&quot;wordInput&quot; type=&quot;text&quot; placeholder=&quot;Наприклад: машина&quot; fdprocessedid=&quot;mfgjqk&quot;&gt;

      &lt;label&gt;&lt;b&gt;Склади (можна вручну):&lt;/b&gt;&lt;/label&gt;
      &lt;input id=&quot;manualSyllables&quot; class=&quot;manual-syllables&quot; type=&quot;text&quot; placeholder=&quot;ма-ши-на&quot; fdprocessedid=&quot;r3dibi&quot;&gt;
      &lt;div class=&quot;hint&quot;&gt;Наприклад: ма-ши-на&lt;/div&gt;

      &lt;button class=&quot;primary-btn&quot; onclick=&quot;createGame()&quot; fdprocessedid=&quot;y7ykhi&quot;&gt;Створити гру&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;card&quot;&gt;
    &lt;div class=&quot;emoji&quot; id=&quot;emojiDisplay&quot;&gt;🧩&lt;/div&gt;
    &lt;h2&gt;Склади слово&lt;/h2&gt;

    &lt;div class=&quot;answer&quot; id=&quot;answerArea&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;syllables&quot; id=&quot;syllableArea&quot;&gt;&lt;/div&gt;

    &lt;div class=&quot;controls&quot;&gt;
      &lt;button class=&quot;accent-btn&quot; onclick=&quot;speakWord()&quot; fdprocessedid=&quot;3m9yl9&quot;&gt;🔊 Озвучити&lt;/button&gt;
      &lt;button class=&quot;danger-btn&quot; onclick=&quot;resetAnswer()&quot; fdprocessedid=&quot;h4kdf&quot;&gt;🔄 Очистити&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;status&quot; id=&quot;status&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;stars&quot; id=&quot;stars&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
let targetWord = &quot;&quot;;
let syllables = [];
let selected = [];

const emojiMap = {
  &quot;мама&quot;: &quot;👩&quot;,
  &quot;тато&quot;: &quot;👨&quot;,
  &quot;кіт&quot;: &quot;🐱&quot;,
  &quot;собака&quot;: &quot;🐶&quot;,
  &quot;машина&quot;: &quot;🚗&quot;,
  &quot;яблуко&quot;: &quot;🍎&quot;,
  &quot;сонце&quot;: &quot;☀️&quot;
};

// Поділ на склади
function splitIntoSyllables(word) {
  const vowels = &quot;аеєиіїоуюя&quot;;
  let result = [];
  let current = &quot;&quot;;

  for (let i = 0; i &lt; word.length; i++) {
    current += word[i];

    if (vowels.includes(word[i].toLowerCase())) {
      let nextVowel = false;

      for (let j = i + 1; j &lt; word.length; j++) {
        if (vowels.includes(word[j].toLowerCase())) {
          nextVowel = true;
          break;
        }
      }

      if (nextVowel) {
        result.push(current);
        current = &quot;&quot;;
      }
    }
  }

  if (current) result.push(current);

  return result.length ? result : [word];
}

function shuffleArray(arr) {
  return [...arr].sort(() =&gt; Math.random() - 0.5);
}

function createGame() {
  targetWord = document.getElementById(&quot;wordInput&quot;).value.trim().toLowerCase();
  if (!targetWord) return;

  const manual = document.getElementById(&quot;manualSyllables&quot;).value.trim();

  if (manual) {
    syllables = manual.split(&quot;-&quot;).map(s =&gt; s.trim().toLowerCase()).filter(Boolean);
  } else {
    syllables = splitIntoSyllables(targetWord);
    document.getElementById(&quot;manualSyllables&quot;).value = syllables.join(&quot;-&quot;);
  }

  selected = [];

  renderAnswerSlots();
  renderSyllables();

  document.getElementById(&quot;status&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;emojiDisplay&quot;).textContent = emojiMap[targetWord] || &quot;🧩&quot;;

  preloadVoices();
}

function renderAnswerSlots() {
  const area = document.getElementById(&quot;answerArea&quot;);
  area.innerHTML = &quot;&quot;;

  for (let i = 0; i &lt; syllables.length; i++) {
    const slot = document.createElement(&quot;div&quot;);
    slot.className = &quot;slot&quot;;
    slot.textContent = selected[i] || &quot;&quot;;
    area.appendChild(slot);
  }
}

function renderSyllables() {
  const area = document.getElementById(&quot;syllableArea&quot;);
  area.innerHTML = &quot;&quot;;

  shuffleArray(syllables).forEach(syllable =&gt; {
    const btn = document.createElement(&quot;button&quot;);
    btn.className = &quot;tile&quot;;
    btn.textContent = syllable;

    btn.onclick = () =&gt; {
      selected.push(syllable);
      btn.classList.add(&quot;used&quot;);

      speakSyllable(syllable);

      renderAnswerSlots();
      checkAnswer();
    };

    area.appendChild(btn);
  });
}

function checkAnswer() {
  if (selected.length !== syllables.length) return;

  const formed = selected.join(&quot;&quot;).toLowerCase();

  if (formed === targetWord) {
    document.getElementById(&quot;status&quot;).textContent = &quot;🎉 Молодець!&quot;;
    document.getElementById(&quot;stars&quot;).textContent = &quot;⭐ ⭐ ⭐&quot;;
    speakWord();

    if (navigator.vibrate) {
      navigator.vibrate([150, 70, 150]);
    }
  } else {
    document.getElementById(&quot;status&quot;).textContent = &quot;🙂 Спробуй ще раз&quot;;
  }
}

function resetAnswer() {
  selected = [];
  renderAnswerSlots();
  renderSyllables();
  document.getElementById(&quot;status&quot;).textContent = &quot;&quot;;
  document.getElementById(&quot;stars&quot;).textContent = &quot;&quot;;
}

// ---------- УКРАЇНСЬКА ОЗВУЧКА ----------
function preloadVoices() {
  speechSynthesis.getVoices();
}

function getBestUkrainianVoice() {
  const voices = speechSynthesis.getVoices();

  return (
    voices.find(v =&gt; v.lang === &quot;uk-UA&quot;) ||
    voices.find(v =&gt; v.lang.toLowerCase().startsWith(&quot;uk&quot;)) ||
    voices.find(v =&gt;
      v.name.toLowerCase().includes(&quot;ukrain&quot;) ||
      v.name.toLowerCase().includes(&quot;укра&quot;)
    ) ||
    null
  );
}

function normalizeUkrainianText(text) {
  return text.toLowerCase().trim();
}

function spellBySyllables(text) {
  if (!syllables.length) return text.split(&quot;&quot;).join(&quot; ... &quot;);
  return syllables.join(&quot; ... &quot;);
}

function speakText(text, isWord = false) {
  speechSynthesis.cancel();

  const voice = getBestUkrainianVoice();
  let spokenText = normalizeUkrainianText(text);

  if (!voice || !voice.lang.toLowerCase().startsWith(&quot;uk&quot;)) {
    spokenText = isWord ? spellBySyllables(text) : text;
  }

  const utterance = new SpeechSynthesisUtterance(spokenText);

  if (voice) {
    utterance.voice = voice;
    utterance.lang = voice.lang;
  } else {
    utterance.lang = &quot;uk-UA&quot;;
  }

  utterance.rate = isWord ? 0.65 : 0.55;
  utterance.pitch = 1.0;
  utterance.volume = 1;

  speechSynthesis.speak(utterance);
}

function speakSyllable(syllable) {
  speakText(syllable, false);
}

function speakWord() {
  if (!targetWord) return;
  speakText(targetWord, true);
}

window.speechSynthesis.onvoiceschanged = () =&gt; {
  preloadVoices();
};

document.addEventListener(&quot;click&quot;, function initSpeech() {
  speechSynthesis.resume();
  preloadVoices();
  document.removeEventListener(&quot;click&quot;, initSpeech);
});
&lt;/script&gt;</description>
            </item>
                    <item>
                <title>2048 6 6</title>
                <link>http://margo.mozello.shop/gry/params/post/5199027/2048-6-6</link>
                <pubDate>Fri, 23 Jan 2026 22:22:00 +0000</pubDate>
                <description>Темна тема&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;4&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;meta charset=&quot;UTF-8&quot;&gt;

&lt;style&gt;
/* ===== ОБГОРТКА З ТЕМАМИ ===== */
.game-theme-wrapper {
    padding: 25px 20px;
    border-radius: 14px;
    font-family: sans-serif;
    text-align: center;
    transition: background-color .3s, color .3s;
}

/* Світла тема */
.game-theme-wrapper.light {
    background: #faf8ef;
    color: #333;
}

/* Темна ЗЕЛЕНА тема */
.game-theme-wrapper.dark {
    background: #0f1f1a;
    color: #e0f2ea;
}

/* Кнопка теми */
.theme-toggle {
    display: inline-block;
    margin-bottom: 15px;
    padding: 8px 16px;
    background: #2d6a4f;
    color: #fff;
    border-radius: 20px;
    cursor: pointer;
    font-size: 14px;
}
.theme-toggle:hover { background: #40916c; }

/* Заголовки */
.game-theme-wrapper.dark h1,
.game-theme-wrapper.dark .info {
    color: #b7e4c7;
}

/* Кнопка нової гри */
#restart {
    margin: 10px 0;
    padding: 8px 16px;
    border-radius: 6px;
    border: none;
    cursor: pointer;
}

/* ===== ДОШКА ГРИ ===== */
#game-board {
    display: grid;
    grid-template-columns: repeat(6, 80px);
    gap: 8px;
    justify-content: center;
    margin: 20px auto;
    padding: 10px;
    border-radius: 10px;
}

/* Темна тема — фон дошки */
.game-theme-wrapper.dark #game-board {
    background: #1b3a2f;
}

/* Клітинки */
.tile {
    width: 110px;
    height: 40px;
    background: #cdc1b4;
    font-size: 24px;
    color: #776e65;
    display: flex;
    justify-content: center;
    align-items: center;
    font-weight: bold;
    border-radius: 5px;
}

/* Кольори плиток */
.tile[data-value=&quot;2&quot;]    { background: #eee4da; }
.tile[data-value=&quot;4&quot;]    { background: #ede0c8; }
.tile[data-value=&quot;8&quot;]    { background: #f2b179; color: #fff; }
.tile[data-value=&quot;16&quot;]   { background: #f59563; color: #fff; }
.tile[data-value=&quot;32&quot;]   { background: #f67c5f; color: #fff; }
.tile[data-value=&quot;64&quot;]   { background: #f65e3b; color: #fff; }
.tile[data-value=&quot;128&quot;]  { background: #edcf72; color: #fff; }
.tile[data-value=&quot;256&quot;]  { background: #edcc61; color: #fff; }
.tile[data-value=&quot;512&quot;]  { background: #edc850; color: #fff; }
.tile[data-value=&quot;1024&quot;] { background: #edc53f; color: #fff; }
.tile[data-value=&quot;2048&quot;] { background: #edc22e; color: #fff; }

/* Повідомлення */
#message {
    position: fixed;
    top: 40%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #ffffffee;
    padding: 25px;
    border-radius: 10px;
    display: none;
    z-index: 10;
}
&lt;/style&gt;

&lt;div class=&quot;game-theme-wrapper light&quot; id=&quot;gameTheme&quot;&gt;

    &lt;div class=&quot;theme-toggle&quot; id=&quot;themeToggle&quot;&gt;🌙 Темна тема&lt;/div&gt;

    &lt;h1&gt;2048 (6×6)&lt;/h1&gt;
    &lt;div class=&quot;info&quot; id=&quot;score&quot;&gt;Очки: 0&lt;/div&gt;
    &lt;div class=&quot;info&quot; id=&quot;best&quot;&gt;Рекорд: 0&lt;/div&gt;
    &lt;button id=&quot;restart&quot; fdprocessedid=&quot;3y1n4&quot;&gt;Нова гра&lt;/button&gt;

    &lt;div id=&quot;game-board&quot;&gt;&lt;/div&gt;

    &lt;div id=&quot;message&quot;&gt;
        &lt;div id=&quot;message-text&quot;&gt;&lt;/div&gt;
        &lt;button id=&quot;continue&quot;&gt;Продовжити&lt;/button&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;script&gt;
/* ===== ПЕРЕМИКАЧ ТЕМИ ===== */
(function () {
    const w = document.getElementById(&quot;gameTheme&quot;);
    const t = document.getElementById(&quot;themeToggle&quot;);
    const saved = localStorage.getItem(&quot;theme2048&quot;);

    if (saved === &quot;dark&quot;) {
        w.classList.replace(&quot;light&quot;, &quot;dark&quot;);
        t.textContent = &quot;☀️ Світла тема&quot;;
    }

    t.onclick = () =&gt; {
        if (w.classList.contains(&quot;dark&quot;)) {
            w.classList.replace(&quot;dark&quot;, &quot;light&quot;);
            t.textContent = &quot;🌙 Темна тема&quot;;
            localStorage.setItem(&quot;theme2048&quot;, &quot;light&quot;);
        } else {
            w.classList.replace(&quot;light&quot;, &quot;dark&quot;);
            t.textContent = &quot;☀️ Світла тема&quot;;
            localStorage.setItem(&quot;theme2048&quot;, &quot;dark&quot;);
        }
    };
})();
&lt;/script&gt;

&lt;script&gt;
/* ===== ГРА 2048 (6x6) ===== */
const board = document.getElementById(&#039;game-board&#039;),
scoreD = document.getElementById(&#039;score&#039;),
bestD = document.getElementById(&#039;best&#039;),
msg = document.getElementById(&#039;message&#039;),
msgT = document.getElementById(&#039;message-text&#039;),
cont = document.getElementById(&#039;continue&#039;);

const SIZE = 6;
let values = [], tiles = [], score = 0, best = 0;
let gameOver = false, allow = false;

best = +localStorage.getItem(&#039;best2048_6x6&#039;) || 0;
bestD.textContent = &#039;Рекорд: &#039; + best;

function save() {
    localStorage.setItem(&#039;g2048v&#039;, JSON.stringify(values));
    localStorage.setItem(&#039;g2048s&#039;, score);
}

function add() {
    const e = values.map((v, i) =&gt; v ? null : i).filter(v =&gt; v !== null);
    if (e.length) values[e[Math.random() * e.length | 0]] = Math.random() &lt; .9 ? 2 : 4;
}

function draw() {
    tiles.forEach((t, i) =&gt; {
        t.textContent = values[i] || &#039;&#039;;
        t.dataset.value = values[i];
    });
    scoreD.textContent = &#039;Очки: &#039; + score;
    if (score &gt; best) {
        best = score;
        bestD.textContent = &#039;Рекорд: &#039; + best;
        localStorage.setItem(&#039;best2048_6x6&#039;, best);
    }
    save();
}

function slide(r) {
    r = r.filter(v =&gt; v);
    for (let i = 0; i &lt; r.length - 1; i++) {
        if (r[i] === r[i + 1]) {
            r[i] *= 2;
            score += r[i];
            r[i + 1] = 0;
        }
    }
    r = r.filter(v =&gt; v);
    while (r.length &lt; SIZE) r.push(0);
    return r;
}

function move(d) {
    if (gameOver) return;
    let moved = false;

    for (let i = 0; i &lt; SIZE; i++) {
        let line = [];
        for (let j = 0; j &lt; SIZE; j++) {
            let x = d === &#039;l&#039; ? i * SIZE + j :
                    d === &#039;r&#039; ? i * SIZE + (SIZE - 1 - j) :
                    d === &#039;u&#039; ? j * SIZE + i :
                                (SIZE - 1 - j) * SIZE + i;
            line.push(values[x]);
        }

        let newLine = slide(line);

        for (let j = 0; j &lt; SIZE; j++) {
            let x = d === &#039;l&#039; ? i * SIZE + j :
                    d === &#039;r&#039; ? i * SIZE + (SIZE - 1 - j) :
                    d === &#039;u&#039; ? j * SIZE + i :
                                (SIZE - 1 - j) * SIZE + i;
            if (values[x] !== newLine[j]) {
                values[x] = newLine[j];
                moved = true;
            }
        }
    }

    if (moved) {
        add();
        draw();
        check();
    }
}

function check() {
    if (!allow &amp;&amp; values.includes(2048)) {
        msgT.textContent = &#039;Ви виграли 🎉&#039;;
        msg.style.display = &#039;block&#039;;
        gameOver = true;
    } else if (!values.includes(0)) {
        msgT.textContent = &#039;Гру завершено&#039;;
        msg.style.display = &#039;block&#039;;
        gameOver = true;
    }
}

function init() {
    board.innerHTML = &#039;&#039;;
    tiles = [];
    values = JSON.parse(localStorage.getItem(&#039;g2048v&#039;)) || Array(36).fill(0);
    score = +localStorage.getItem(&#039;g2048s&#039;) || 0;

    for (let i = 0; i &lt; 36; i++) {
        let d = document.createElement(&#039;div&#039;);
        d.className = &#039;tile&#039;;
        board.appendChild(d);
        tiles.push(d);
    }

    if (!values.some(v =&gt; v)) { add(); add(); }
    draw();
}

/* ⬇️ ВИПРАВЛЕННЯ: сторінка більше НЕ скролиться */
document.addEventListener(&#039;keydown&#039;, function (e) {
    const keys = {
        ArrowLeft: &#039;l&#039;,
        ArrowRight: &#039;r&#039;,
        ArrowUp: &#039;u&#039;,
        ArrowDown: &#039;d&#039;
    };
    if (keys[e.key]) {
        e.preventDefault();
        move(keys[e.key]);
    }
});

document.getElementById(&#039;restart&#039;).onclick = () =&gt; {
    values = Array(36).fill(0);
    score = 0;
    gameOver = false;
    allow = false;
    add(); add();
    msg.style.display = &#039;none&#039;;
    draw();
};

cont.onclick = () =&gt; {
    gameOver = false;
    allow = true;
    msg.style.display = &#039;none&#039;;
};

init();
&lt;/script&gt;</description>
            </item>
                    <item>
                <title>реверсі</title>
                <link>http://margo.mozello.shop/gry/params/post/5144256/revers</link>
                <pubDate>Sat, 04 Oct 2025 19:55:00 +0000</pubDate>
                <description>&lt;img src=&quot;https://site-2669532.mozfiles.com/files/2669532/medium/gra_revers.jpg&quot; style=&quot;width: 189px;&quot;&gt;У світі настільних ігор є одна, яка поєднує простоту правил і глибину стратегії — це Реверсі. Вона не потребує складного обладнання, але здатна захопити на години. У цій бесіді ми розглянемо, чому Реверсі варта вашої уваги, як у неї грати, і що вона дає гравцеві.

&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;1&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;



  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;title&gt;Реверсі: Гравець vs Комп&#039;ютер&lt;/title&gt;
  &lt;style&gt;
    canvas { background: #0a0; display: block; margin: 20px auto; }
    body { text-align: center; font-family: sans-serif; }
    details { margin: 20px auto; width: 80%; text-align: left; }
    summary { font-weight: bold; cursor: pointer; }
  &lt;/style&gt;


  &lt;h1&gt;Гра Реверсі&lt;/h1&gt;
  &lt;canvas id=&quot;board&quot; width=&quot;320&quot; height=&quot;320&quot;&gt;&lt;/canvas&gt;
  &lt;p&gt;Поточний гравець: &lt;span id=&quot;player&quot;&gt;Гравець (Чорний)&lt;/span&gt;&lt;/p&gt;

  &lt;details&gt;
    &lt;summary&gt;📘 Правила гри та інструкція&lt;/summary&gt;
    &lt;p&gt;&lt;b&gt;Мета гри:&lt;/b&gt; захопити більше клітинок, ніж суперник, перетворюючи його фішки на свої.&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;Початок:&lt;/b&gt; гра починається з 4 фішками в центрі дошки. Гравець — чорний, комп’ютер — білий.&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;Хід:&lt;/b&gt; фішка ставиться так, щоб між новою фішкою і вже наявною була хоча б одна фішка суперника. Всі такі фішки перевертаються.&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;Коли немає ходів:&lt;/b&gt; якщо гравець не має допустимих ходів — хід переходить супернику.&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;Завершення гри:&lt;/b&gt; коли дошка заповнена або жоден гравець не має ходів. Перемагає той, у кого більше фішок.&lt;/p&gt;
  &lt;/details&gt;

  &lt;script&gt;
    const canvas = document.getElementById(&quot;board&quot;);
    const ctx = canvas.getContext(&quot;2d&quot;);
    const size = 8;
    const cell = canvas.width / size;
    let board = Array(size).fill().map(() =&gt; Array(size).fill(null));
    board[3][3] = board[4][4] = &quot;W&quot;;
    board[3][4] = board[4][3] = &quot;B&quot;;
    let current = &quot;B&quot;;

    function drawBoard() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (let x = 0; x &lt; size; x++) {
        for (let y = 0; y &lt; size; y++) {
          ctx.strokeRect(x * cell, y * cell, cell, cell);
          if (board[x][y]) {
            ctx.beginPath();
            ctx.arc(x * cell + cell / 2, y * cell + cell / 2, cell / 2 - 4, 0, Math.PI * 2);
            ctx.fillStyle = board[x][y] === &quot;B&quot; ? &quot;black&quot; : &quot;white&quot;;
            ctx.fill();
          }
        }
      }
    }

    function isValid(x, y, player) {
      if (board[x][y]) return false;
      const opp = player === &quot;B&quot; ? &quot;W&quot; : &quot;B&quot;;
      const dirs = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];
      for (let [dx, dy] of dirs) {
        let nx = x + dx, ny = y + dy, found = false;
        while (nx &gt;= 0 &amp;&amp; ny &gt;= 0 &amp;&amp; nx &lt; size &amp;&amp; ny &lt; size) {
          if (board[nx][ny] === opp) found = true;
          else if (board[nx][ny] === player &amp;&amp; found) return true;
          else break;
          nx += dx; ny += dy;
        }
      }
      return false;
    }

    function flip(x, y, player) {
      board[x][y] = player;
      const opp = player === &quot;B&quot; ? &quot;W&quot; : &quot;B&quot;;
      const dirs = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];
      for (let [dx, dy] of dirs) {
        let nx = x + dx, ny = y + dy, path = [];
        while (nx &gt;= 0 &amp;&amp; ny &gt;= 0 &amp;&amp; nx &lt; size &amp;&amp; ny &lt; size) {
          if (board[nx][ny] === opp) path.push([nx, ny]);
          else if (board[nx][ny] === player) {
            for (let [px, py] of path) board[px][py] = player;
            break;
          } else break;
          nx += dx; ny += dy;
        }
      }
    }

    function getValidMoves(player) {
      let moves = [];
      for (let x = 0; x &lt; size; x++) {
        for (let y = 0; y &lt; size; y++) {
          if (isValid(x, y, player)) moves.push([x, y]);
        }
      }
      return moves;
    }

    function countDiscs() {
      let black = 0, white = 0;
      for (let row of board) {
        for (let cell of row) {
          if (cell === &quot;B&quot;) black++;
          if (cell === &quot;W&quot;) white++;
        }
      }
      return { black, white };
    }

    function checkEndGame() {
      const movesB = getValidMoves(&quot;B&quot;);
      const movesW = getValidMoves(&quot;W&quot;);
      const full = board.flat().every(cell =&gt; cell !== null);
      if ((movesB.length === 0 &amp;&amp; movesW.length === 0) || full) {
        const { black, white } = countDiscs();
        let result = &quot;&quot;;
        if (black &gt; white) result = &quot;Ви перемогли!&quot;;
        else if (white &gt; black) result = &quot;Комп’ютер переміг!&quot;;
        else result = &quot;Нічия!&quot;;
        alert(`${result}\nЧорних: ${black}\nБілих: ${white}`);
      }
    }

    function checkTurn() {
      let moves = getValidMoves(current);
      if (moves.length === 0) {
        alert(&quot;Ходів немає. Хід переходить супернику.&quot;);
        current = current === &quot;B&quot; ? &quot;W&quot; : &quot;B&quot;;
        document.getElementById(&quot;player&quot;).textContent =
          current === &quot;B&quot; ? &quot;Гравець (Чорний)&quot; : &quot;Комп&#039;ютер (Білий)&quot;;
        drawBoard();
        if (current === &quot;W&quot;) {
          setTimeout(computerMove, 500);
        }
      }
    }

    function computerMove() {
      let moves = getValidMoves(&quot;W&quot;);
      if (moves.length &gt; 0) {
        let [x, y] = moves[0];
        flip(x, y, &quot;W&quot;);
        current = &quot;B&quot;;
        document.getElementById(&quot;player&quot;).textContent = &quot;Гравець (Чорний)&quot;;
        drawBoard();
        checkEndGame();
        checkTurn();
      } else {
        alert(&quot;Комп&#039;ютер не має ходів. Хід переходить гравцю.&quot;);
        current = &quot;B&quot;;
        document.getElementById(&quot;player&quot;).textContent = &quot;Гравець (Чорний)&quot;;
        drawBoard();
        checkEndGame();
        checkTurn();
      }
    }

    canvas.addEventListener(&quot;click&quot;, e =&gt; {
      if (current !== &quot;B&quot;) return;
      const x = Math.floor(e.offsetX / cell);
      const y = Math.floor(e.offsetY / cell);
      if (isValid(x, y, &quot;B&quot;)) {
        flip(x, y, &quot;B&quot;);
        current = &quot;W&quot;;
        document.getElementById(&quot;player&quot;).textContent = &quot;Комп&#039;ютер (Білий)&quot;;
        drawBoard();
        checkEndGame();
        setTimeout(computerMove, 500);
      } else {
        checkTurn();
      }
    });

    drawBoard();
  &lt;/script&gt;</description>
            </item>
                    <item>
                <title>Мозаїка майстрів 7</title>
                <link>http://margo.mozello.shop/gry/params/post/5141570/mozaka-majstrv-7</link>
                <pubDate>Thu, 02 Oct 2025 14:15:00 +0000</pubDate>
                <description>&lt;span style=&quot;text-align: start; font-weight: 400; font-style: normal&quot;&gt;Права кнопка миші — поворот блоку, Середня кнопка/подвійне торкання — перевертання, Кнопка &quot;Скасувати&quot; — скасування ходу&lt;br&gt;на телефоні поворот блоку інший. Гра поводитися трохи дивно і треба призвичаїтись., але кмітлива дитина розбереться&lt;br&gt;&lt;/span&gt;

&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;2 жовтня 2025&lt;/p&gt;


    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Мозаїка Майстрів — Версія 1.9&lt;/title&gt;
    &lt;style&gt;
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
            padding: 10px;
            background-color: #8A2BE2; /* Фіолетовий фон сторінки */
            font-family: Arial, sans-serif;
            overflow: auto;
        }

        #mainGameContainer {
            display: flex;
            align-items: flex-start;
            justify-content: center;
            gap: 20px;
            margin-top: 20px;
        }

        #gridContainer {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        #gameCanvas {
            border: 2px solid #333;
            background-color: #98FF98; /* Салатовий фон гри */
            max-width: 100%;
            height: auto;
        }

        #nextBlocks {
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
            margin-top: 0;
            flex-wrap: nowrap;
            width: auto;
            max-width: 100px;
            gap: 10px;
        }

        .blockCanvas {
            border: 1px solid #ccc;
            cursor: grab;
            width: 80px;
            height: 80px;
            margin: 0;
        }

        .blockCanvas.dragging {
            opacity: 0.5;
            cursor: grabbing;
        }

        #score, #highScore {
            font-size: 20px;
            margin-top: 10px;
        }

        #bonusMessage {
            display: none;
            position: fixed;
            top: 20%;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(0, 128, 0, 0.8);
            color: white;
            padding: 10px 20px;
            border-radius: 5px;
            z-index: 1000;
            font-size: 18px;
        }

        #gameOver, #pauseOverlay {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 15px;
            border-radius: 10px;
            text-align: center;
            z-index: 1000;
        }

        button {
            margin-top: 10px;
            padding: 8px 16px;
            font-size: 14px;
            cursor: pointer;
        }

        h2 {
            margin: 10px 0;
        }

        p {
            margin: 5px 0;
        }

        .accordion {
            width: 100%;
            max-width: 500px;
            margin-top: 20px;
        }

        .accordion-item {
            border: 1px solid #333;
            margin-bottom: 5px;
            border-radius: 5px;
        }

        .accordion-header {
            background-color: #ddd;
            padding: 10px;
            cursor: pointer;
            font-size: 18px;
            font-weight: bold;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .accordion-header::after {
            content: &#039;▼&#039;;
            font-size: 14px;
        }

        .accordion-header.active::after {
            content: &#039;▲&#039;;
        }

        .accordion-content {
            display: none;
            padding: 10px;
            background-color: #fff;
        }

        .accordion-content.active {
            display: block;
        }

        .accordion-content table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 15px;
        }

        .accordion-content th, .accordion-content td {
            border: 1px solid #333;
            padding: 8px;
            text-align: center;
        }

        .accordion-content th {
            background-color: #ddd;
        }

        .accordion-content pre {
            margin: 0;
            font-size: 12px;
        }

        .accordion-content canvas {
            border: 1px solid #ccc;
        }
    &lt;/style&gt;


    &lt;h2&gt;Мозаїка Майстрів — Версія 1.9&lt;/h2&gt;
    &lt;p&gt;Права кнопка миші — поворот блоку, Середня кнопка/подвійне торкання — перевертання, Кнопка &quot;Скасувати&quot; — скасування ходу&lt;/p&gt;

    &lt;div id=&quot;mainGameContainer&quot;&gt;
        &lt;div id=&quot;gridContainer&quot;&gt;
            &lt;canvas id=&quot;gameCanvas&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&lt;/canvas&gt;
            &lt;button id=&quot;pauseButton&quot; fdprocessedid=&quot;rcbg5m&quot;&gt;Пауза&lt;/button&gt;
            &lt;button id=&quot;undoButton&quot; disabled=&quot;&quot;&gt;Скасувати&lt;/button&gt;
            &lt;div id=&quot;score&quot;&gt;Очки: 0&lt;/div&gt;
            &lt;div id=&quot;highScore&quot;&gt;Рекорд: 0&lt;/div&gt;
        &lt;/div&gt;
        &lt;div id=&quot;nextBlocks&quot;&gt;
            &lt;canvas id=&quot;block1&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
            &lt;canvas id=&quot;block2&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
            &lt;canvas id=&quot;block3&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div id=&quot;bonusMessage&quot;&gt;&lt;/div&gt;
    &lt;div id=&quot;gameOver&quot;&gt;
        &lt;h2&gt;Гра закінчена!&lt;/h2&gt;
        &lt;p id=&quot;finalScore&quot;&gt;&lt;/p&gt;
        &lt;button onclick=&quot;restartGame()&quot;&gt;Грати знову&lt;/button&gt;
    &lt;/div&gt;
    &lt;div id=&quot;pauseOverlay&quot;&gt;
        &lt;h2&gt;Гра на паузі&lt;/h2&gt;
        &lt;button onclick=&quot;togglePause()&quot;&gt;Відновити&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion&quot;&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Таблиця блоків&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;table&gt;
                    &lt;thead&gt;
                        &lt;tr&gt;
                            &lt;th&gt;Назва&lt;/th&gt;
                            &lt;th&gt;Зображення&lt;/th&gt;
                            &lt;th&gt;Структура&lt;/th&gt;
                            &lt;th&gt;Використання&lt;/th&gt;
                        &lt;/tr&gt;
                    &lt;/thead&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Одинарний&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSingle&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення окремих клітинок&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;L-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeL&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для кутів або вузьких просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;T-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeT&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1],&lt;br&gt;[0, 1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для горизонтальних ліній з виступом&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (4)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI4&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Квадрат&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSquare&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для компактних квадратних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Z-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeZ&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 0],&lt;br&gt;[0, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для зміщених &quot;змійок&quot;&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (5)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI5&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (3)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для середніх рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (2)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для коротких рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 2x2&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0],&lt;br&gt;[0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення діагональних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 3x3&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0, 0],&lt;br&gt;[0, 1, 0],&lt;br&gt;[0, 0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих діагональних ліній&lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                &lt;/table&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Інструкція&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;h3&gt;Мета гри&lt;/h3&gt;
                &lt;p&gt;&quot;Мозаїка Майстрів&quot; — це головоломка, де гравець розміщує блоки на сітці 10x10, щоб очищати цілі рядки або стовпці. Мета — набрати якомога більше очок і встановити рекорд. Гра закінчується, коли жоден блок не можна розмістити.&lt;/p&gt;
                
                &lt;h3&gt;Правила гри&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Ігрове поле&lt;/b&gt;: Сітка 10x10, де клітинки можуть бути порожніми або заповненими.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Черга блоків&lt;/b&gt;: До трьох блоків відображаються справа для розміщення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Розміщення&lt;/b&gt;: Перетягуйте блоки на сітку. Розміщення можливе лише у вільних місцях.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Очищення ліній&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;Повний рядок або стовпець очищається.&lt;/li&gt;
                            &lt;li&gt;1 лінія: 100 очок.&lt;/li&gt;
                            &lt;li&gt;2+ ліній: 100 + 50 за кожну додаткову (наприклад, 2 лінії = 150 очок).&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Бонус за очищення поля&lt;/b&gt;: 25% від суми очок, якщо поле порожнє.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Рекорд&lt;/b&gt;: Зберігається у браузері, відображається під час гри та після завершення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Кінець гри&lt;/b&gt;: Гра закінчується, якщо блоки неможливо розмістити.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Дії гравця&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Перетягування&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;ПК: Лівою кнопкою миші.&lt;/li&gt;
                            &lt;li&gt;Сенсорні пристрої: Торкніться та перетягніть.&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Поворот&lt;/b&gt;: Права кнопка миші або довге натискання (300мс).&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Перевертання&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;ПК: Середня кнопка миші або подвійне клацання.&lt;/li&gt;
                            &lt;li&gt;Сенсорні пристрої: Двохпальцевий тап.&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Скасування ходу&lt;/b&gt;: Кнопка &quot;Скасувати&quot; для останнього ходу.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Пауза&lt;/b&gt;: Кнопка &quot;Пауза&quot;/&quot;Відновити&quot;.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Перезапуск&lt;/b&gt;: Кнопка &quot;Грати знову&quot; на екрані &quot;Гра закінчена&quot;.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Поради&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;Плануйте ходи, щоб створювати повні лінії.&lt;/li&gt;
                    &lt;li&gt;Використовуйте одинарний блок для прогалин.&lt;/li&gt;
                    &lt;li&gt;Скасовуйте невдалі ходи.&lt;/li&gt;
                    &lt;li&gt;Намагайтеся очищати кілька ліній для бонусів.&lt;/li&gt;
                    &lt;li&gt;Експериментуйте з діагональними блоками для унікальних комбінацій.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;script&gt;
        function toggleAccordion(header) {
            const content = header.nextElementSibling;
            const isActive = content.classList.contains(&#039;active&#039;);
            document.querySelectorAll(&#039;.accordion-content&#039;).forEach(c =&gt; c.classList.remove(&#039;active&#039;));
            document.querySelectorAll(&#039;.accordion-header&#039;).forEach(h =&gt; h.classList.remove(&#039;active&#039;));
            if (!isActive) {
                content.classList.add(&#039;active&#039;);
                header.classList.add(&#039;active&#039;);
            }
        }

        const shapes = {
            single: [[1]],
            l: [[1, 1], [1, 0]],
            t: [[1, 1, 1], [0, 1, 0]],
            i4: [[1, 1, 1, 1]],
            square: [[1, 1], [1, 1]],
            z: [[1, 1, 0], [0, 1, 1]],
            i5: [[1, 1, 1, 1, 1]],
            i3: [[1, 1, 1]],
            i2: [[1, 1]],
            diagonal2: [[1, 0], [0, 1]],
            diagonal3: [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
        };

        const colors = [&#039;#FF0000&#039;, &#039;#FFA500&#039;, &#039;#FFFF00&#039;, &#039;#008000&#039;, &#039;#00CED1&#039;, &#039;#0000FF&#039;, &#039;#800080&#039;]; // Веселка: червоний, оранжевий, жовтий, зелений, блакитний, синій, фіолетовий

        const cellSize = 30;
        const gridSize = 10;

        let grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
        let currentBlocks = [];
        let selectedBlock = null;
        let score = 0;
        let highScore = localStorage.getItem(&#039;blockLegendHighScore&#039;) || 0;
        let gameActive = true;
        let gamePaused = false;
        let lastMove = null;

        const gameCanvas = document.getElementById(&#039;gameCanvas&#039;);
        const ctx = gameCanvas.getContext(&#039;2d&#039;);
        const scoreElement = document.getElementById(&#039;score&#039;);
        const highScoreElement = document.getElementById(&#039;highScore&#039;);
        const bonusMessageElement = document.getElementById(&#039;bonusMessage&#039;);
        const gameOverElement = document.getElementById(&#039;gameOver&#039;);
        const finalScoreElement = document.getElementById(&#039;finalScore&#039;);
        const pauseButton = document.getElementById(&#039;pauseButton&#039;);
        const undoButton = document.getElementById(&#039;undoButton&#039;);
        const pauseOverlay = document.getElementById(&#039;pauseOverlay&#039;);

        highScoreElement.textContent = `Рекорд: ${highScore}`;

        function drawGrid() {
            ctx.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
            for (let y = 0; y &lt; gridSize; y++) {
                for (let x = 0; x &lt; gridSize; x++) {
                    ctx.strokeStyle = &#039;#ddd&#039;;
                    ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize);
                    if (grid[y][x]) {
                        ctx.fillStyle = grid[y][x];
                        ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize);
                    }
                }
            }
        }

        function drawPreview(shape, x, y, valid) {
            drawGrid();
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        ctx.fillStyle = valid ? &#039;rgba(0, 255, 0, 0.5)&#039; : &#039;rgba(255, 0, 0, 0.5)&#039;;
                        ctx.fillRect((x + sx) * cellSize, (y + sy) * cellSize, cellSize, cellSize);
                    }
                }
            }
        }

        function canPlaceBlock(shape, x, y) {
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        if (x + sx &lt; 0 || x + sx &gt;= gridSize || y + sy &lt; 0 || y + sy &gt;= gridSize || grid[y + sy][x + sx]) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        function placeBlock(shape, color, x, y, blockIndex) {
            lastMove = {
                grid: grid.map(row =&gt; [...row]),
                score,
                block: { shape, color },
                blockIndex
            };
            undoButton.disabled = false;
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        grid[y + sy][x + sx] = color;
                    }
                }
            }
            drawGrid();
            checkLines();
        }

        function rotateShape(shape) {
            return shape[0].map((_, col) =&gt; shape.map(row =&gt; row[col]).reverse());
        }

        function flipShape(shape) {
            return shape.map(row =&gt; row.reverse());
        }

        function generateBlock() {
            const shapeKeys = Object.keys(shapes);
            const randomShapeKey = shapeKeys[Math.floor(Math.random() * shapeKeys.length)];
            const shape = shapes[randomShapeKey];
            const color = colors[Math.floor(Math.random() * colors.length)];
            return { shape, color };
        }

        function generateBlocks() {
            while (currentBlocks.length &lt; 3) {
                currentBlocks.push(generateBlock());
            }
            for (let i = 0; i &lt; 3; i++) {
                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
            }
        }

        function drawBlock(index, shape, color) {
            const blockCanvas = document.getElementById(`block${index + 1}`);
            const bctx = blockCanvas.getContext(&#039;2d&#039;);
            bctx.clearRect(0, 0, blockCanvas.width, blockCanvas.height);
            const blockSize = 20;
            const offsetX = (blockCanvas.width - shape[0].length * blockSize) / 2;
            const offsetY = (blockCanvas.height - shape.length * blockSize) / 2;
            const gradient = bctx.createLinearGradient(0, 0, 0, blockSize * shape.length);
            gradient.addColorStop(0, color);
            gradient.addColorStop(1, lightenColor(color, 0.3)); // Світлий градієнт для огранки
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        bctx.fillStyle = gradient;
                        bctx.fillRect(offsetX + sx * blockSize, offsetY + sy * blockSize, blockSize, blockSize);
                        bctx.strokeStyle = lightenColor(color, 0.6); // Світлий контур
                        bctx.lineWidth = 2;
                        bctx.strokeRect(offsetX + sx * blockSize, offsetY + sy * blockSize, blockSize, blockSize);
                    }
                }
            }
        }

        // Функція для освітлення кольору
        function lightenColor(color, percent) {
            const num = parseInt(color.replace(&quot;#&quot;, &quot;&quot;), 16);
            const r = Math.min(255, Math.floor((num &gt;&gt; 16) * (1 + percent)));
            const g = Math.min(255, Math.floor(((num &gt;&gt; 8) &amp; 0x00FF) * (1 + percent)));
            const b = Math.min(255, Math.floor((num &amp; 0x0000FF) * (1 + percent)));
            return `#${(r &lt;&lt; 16 | g &lt;&lt; 8 | b).toString(16).padStart(6, &#039;0&#039;)}`;
        }

        function drawShapePreview(id, shape, color) {
            const canvas = document.getElementById(id);
            const ctx = canvas.getContext(&#039;2d&#039;);
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const blockSize = 15;
            const offsetX = (canvas.width - shape[0].length * blockSize) / 2;
            const offsetY = (canvas.height - shape.length * blockSize) / 2;
            const gradient = ctx.createLinearGradient(0, 0, 0, blockSize * shape.length);
            gradient.addColorStop(0, color);
            gradient.addColorStop(1, lightenColor(color, 0.3));
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        ctx.fillStyle = gradient;
                        ctx.fillRect(offsetX + sx * blockSize, offsetY + sy * blockSize, blockSize, blockSize);
                        ctx.strokeStyle = lightenColor(color, 0.6);
                        ctx.lineWidth = 1;
                        ctx.strokeRect(offsetX + sx * blockSize, offsetY + sy * blockSize, blockSize, blockSize);
                    }
                }
            }
        }

        function showBonusMessage(message) {
            bonusMessageElement.textContent = message;
            bonusMessageElement.style.display = &#039;block&#039;;
            setTimeout(() =&gt; {
                bonusMessageElement.style.display = &#039;none&#039;;
            }, 2000);
        }

        function checkLines() {
            let linesCleared = 0;
            for (let i = 0; i &lt; gridSize; i++) {
                if (grid[i].every(cell =&gt; cell)) {
                    grid[i] = Array(gridSize).fill(null);
                    linesCleared++;
                }
                let colFull = true;
                for (let j = 0; j &lt; gridSize; j++) {
                    if (!grid[j][i]) {
                        colFull = false;
                        break;
                    }
                }
                if (colFull) {
                    for (let j = 0; j &lt; gridSize; j++) {
                        grid[j][i] = null;
                    }
                    linesCleared++;
                }
            }
            if (linesCleared &gt; 0) {
                let lineBonus = linesCleared === 1 ? 100 : 100 + (linesCleared - 1) * 50;
                score += lineBonus;
                if (linesCleared &gt; 1) {
                    showBonusMessage(`Бонус за ${linesCleared} лінії: +${lineBonus} очок`);
                }
                const isGridEmpty = grid.every(row =&gt; row.every(cell =&gt; !cell));
                if (isGridEmpty &amp;&amp; score &gt; 0) {
                    const clearBonus = Math.floor(score * 0.25);
                    score += clearBonus;
                    showBonusMessage(`Бонус за повне очищення поля: +${clearBonus} очок`);
                }
                scoreElement.textContent = `Очки: ${score}`;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    highScoreElement.textContent = `Рекорд: ${highScore}`;
                }
            }
            drawGrid();
            checkGameOver();
        }

        function checkGameOver() {
            console.log(&#039;Перевірка стану гри. Кількість блоків:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
            if (currentBlocks.length === 0) {
                console.log(&#039;Черга порожня, генеруємо нові блоки&#039;);
                setTimeout(() =&gt; {
                    generateBlocks();
                    console.log(&#039;Нові блоки згенеровано, нова черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                }, 0);
                return;
            }
            let canPlaceAny = false;
            for (let block of currentBlocks) {
                for (let y = 0; y &lt; gridSize; y++) {
                    for (let x = 0; x &lt; gridSize; x++) {
                        if (canPlaceBlock(block.shape, x, y)) {
                            canPlaceAny = true;
                            break;
                        }
                    }
                    if (canPlaceAny) break;
                }
                if (canPlaceAny) break;
            }
            console.log(&#039;Чи можна розмістити блок:&#039;, canPlaceAny);
            if (!canPlaceAny) {
                gameActive = false;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    console.log(&#039;Новий рекорд на кінці гри:&#039;, highScore);
                }
                finalScoreElement.textContent = `Ваш рахунок: ${score}\nРекорд: ${highScore}`;
                gameOverElement.style.display = &#039;block&#039;;
                console.log(&#039;Гра закінчена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
            }
        }

        function restartGame() {
            grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
            score = 0;
            scoreElement.textContent = `Очки: ${score}`;
            highScoreElement.textContent = `Рекорд: ${highScore}`;
            gameOverElement.style.display = &#039;none&#039;;
            gamePaused = false;
            pauseButton.textContent = &#039;Пауза&#039;;
            pauseOverlay.style.display = &#039;none&#039;;
            undoButton.disabled = true;
            lastMove = null;
            gameActive = true;
            currentBlocks = [];
            generateBlocks();
            drawGrid();
            console.log(&#039;Гра перезапущена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function undoMove() {
            if (!lastMove || !gameActive || gamePaused) return;
            grid = lastMove.grid.map(row =&gt; [...row]);
            score = lastMove.score;
            currentBlocks.splice(lastMove.blockIndex, 0, lastMove.block);
            scoreElement.textContent = `Очки: ${score}`;
            undoButton.disabled = true;
            lastMove = null;
            for (let i = 0; i &lt; 3; i++) {
                const blockCanvas = document.getElementById(`block${i + 1}`);
                blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                if (i &lt; currentBlocks.length) {
                    drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                }
            }
            drawGrid();
            console.log(&#039;Хід скасовано. Поточна черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
        }

        function togglePause() {
            if (!gameActive) return;
            gamePaused = !gamePaused;
            pauseButton.textContent = gamePaused ? &#039;Відновити&#039; : &#039;Пауза&#039;;
            pauseOverlay.style.display = gamePaused ? &#039;block&#039; : &#039;none&#039;;
            console.log(&#039;Гра на паузі:&#039;, gamePaused);
        }

        pauseButton.addEventListener(&#039;click&#039;, togglePause);
        undoButton.addEventListener(&#039;click&#039;, undoMove);

        let touchStartX = 0;
        let touchStartY = 0;
        const blockCanvases = document.querySelectorAll(&#039;.blockCanvas&#039;);
        blockCanvases.forEach(canvas =&gt; {
            canvas.addEventListener(&#039;dragstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                selectedBlock = currentBlocks[index];
                canvas.classList.add(&#039;dragging&#039;);
                e.dataTransfer.setData(&#039;text/plain&#039;, index);
                console.log(&#039;Початок перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
            });

            canvas.addEventListener(&#039;dragend&#039;, (e) =&gt; {
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Кінець перетягування&#039;);
            });

            canvas.addEventListener(&#039;contextmenu&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                currentBlocks[index].shape = rotateShape(currentBlocks[index].shape);
                drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                console.log(&#039;Блок повернуто:&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
            });

            canvas.addEventListener(&#039;mousedown&#039;, (e) =&gt; {
                if (e.button === 1) {
                    e.preventDefault();
                    if (!gameActive || gamePaused) return;
                    const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (середня кнопка):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });

            canvas.addEventListener(&#039;dblclick&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (подвійне клацання):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });

            canvas.addEventListener(&#039;touchstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    selectedBlock = currentBlocks[index];
                    canvas.classList.add(&#039;dragging&#039;);

                    // Record initial touch position for movement tolerance
                    const touch = e.touches[0];
                    touchStartX = touch.clientX;
                    touchStartY = touch.clientY;

                    // Two-finger tap detection for flipping
                    if (e.touches.length === 2) {
                        const touch1 = e.touches[0];
                        const touch2 = e.touches[1];
                        const moveTolerance = 10; // Pixels of movement allowed
                        const dx1 = Math.abs(touch1.clientX - touchStartX);
                        const dy1 = Math.abs(touch1.clientY - touchStartY);
                        const dx2 = Math.abs(touch2.clientX - touchStartX);
                        const dy2 = Math.abs(touch2.clientY - touchStartY);
                        if (dx1 &lt; moveTolerance &amp;&amp; dy1 &lt; moveTolerance &amp;&amp; dx2 &lt; moveTolerance &amp;&amp; dy2 &lt; moveTolerance) {
                            currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                            drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                            console.log(&#039;Блок перевернуто (двохпальцевий тап):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                            e.preventDefault(); // Prevent default behavior (e.g., zoom)
                        }
                        return; // Exit early to avoid long-press interference
                    }

                    // Long-press detection for rotation
                    let touchStartTime = Date.now();
                    const touchHoldTimeout = setTimeout(() =&gt; {
                        if (Date.now() - touchStartTime &gt;= 300 &amp;&amp; e.touches.length === 1) { // Reduced to 300ms
                            currentBlocks[index].shape = rotateShape(currentBlocks[index].shape);
                            drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                            console.log(&#039;Блок повернуто (довге натискання):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                        }
                    }, 300);

                    // Cancel timeout on touchend or touchmove
                    const touchEndOrMove = (event) =&gt; {
                        const currentTouch = event.touches[0] || event.changedTouches[0];
                        const dx = Math.abs(currentTouch.clientX - touchStartX);
                        const dy = Math.abs(currentTouch.clientY - touchStartY);
                        if (dx &gt; 10 || dy &gt; 10) { // Cancel if significant movement
                            clearTimeout(touchHoldTimeout);
                        }
                    };
                    canvas.addEventListener(&#039;touchend&#039;, touchEndOrMove, { once: true });
                    canvas.addEventListener(&#039;touchmove&#039;, touchEndOrMove, { once: true });

                    console.log(&#039;Початок сенсорного перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
                } else {
                    console.error(&#039;Помилка: невалідний індекс блоку на touchstart&#039;, index);
                }
            });

            canvas.addEventListener(&#039;touchmove&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.touches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                const valid = canPlaceBlock(selectedBlock.shape, x, y);
                drawPreview(selectedBlock.shape, x, y, valid);
            });

            canvas.addEventListener(&#039;touchend&#039;, (e) =&gt; {
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.changedTouches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                console.log(`Сенсорне розміщення: координати (${x}, ${y}), індекс: ${index}, блок:`, JSON.stringify(selectedBlock));
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    if (canPlaceBlock(selectedBlock.shape, x, y)) {
                        placeBlock(selectedBlock.shape, selectedBlock.color, x, y, index);
                        currentBlocks.splice(index, 1);
                        console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                        for (let i = 0; i &lt; 3; i++) {
                            const blockCanvas = document.getElementById(`block${i + 1}`);
                            blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                            if (i &lt; currentBlocks.length) {
                                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                            }
                        }
                        checkGameOver();
                        selectedBlock = null;
                    } else {
                        console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                    }
                } else {
                    console.error(&#039;Помилка: невалідний індекс блоку на touchend&#039;, index);
                }
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Сенсорне розміщення завершено&#039;);
            });
        });

        gameCanvas.addEventListener(&#039;dragover&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const valid = canPlaceBlock(selectedBlock.shape, x, y);
            drawPreview(selectedBlock.shape, x, y, valid);
        });

        gameCanvas.addEventListener(&#039;drop&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const index = parseInt(e.dataTransfer.getData(&#039;text/plain&#039;));
            console.log(`Розміщення через drag: координати (${x}, ${y}), індекс: ${index}, блок:`, JSON.stringify(selectedBlock));
            if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                if (canPlaceBlock(selectedBlock.shape, x, y)) {
                    placeBlock(selectedBlock.shape, selectedBlock.color, x, y, index);
                    currentBlocks.splice(index, 1);
                    console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                    for (let i = 0; i &lt; 3; i++) {
                        const blockCanvas = document.getElementById(`block${i + 1}`);
                        blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                        if (i &lt; currentBlocks.length) {
                            drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                        }
                    }
                    checkGameOver();
                    selectedBlock = null;
                } else {
                    console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                }
            } else {
                console.error(&#039;Помилка: невалідний індекс блоку на drop&#039;, index);
            }
            drawGrid();
        });

        // Ініціалізація попередніх зображень блоків
        drawShapePreview(&#039;shapeSingle&#039;, shapes.single, colors[0]);
        drawShapePreview(&#039;shapeL&#039;, shapes.l, colors[1]);
        drawShapePreview(&#039;shapeT&#039;, shapes.t, colors[2]);
        drawShapePreview(&#039;shapeI4&#039;, shapes.i4, colors[3]);
        drawShapePreview(&#039;shapeSquare&#039;, shapes.square, colors[4]);
        drawShapePreview(&#039;shapeZ&#039;, shapes.z, colors[5]);
        drawShapePreview(&#039;shapeI5&#039;, shapes.i5, colors[0]);
        drawShapePreview(&#039;shapeI3&#039;, shapes.i3, colors[1]);
        drawShapePreview(&#039;shapeI2&#039;, shapes.i2, colors[2]);
        drawShapePreview(&#039;shapeDiagonal2&#039;, shapes.diagonal2, colors[3]);
        drawShapePreview(&#039;shapeDiagonal3&#039;, shapes.diagonal3, colors[4]);

        generateBlocks();
        drawGrid();
        console.log(&#039;Гра ініціалізована — Мозаїка Майстрів Версія 1.9&#039;);
    &lt;/script&gt;</description>
            </item>
                    <item>
                <title>мм6</title>
                <link>http://margo.mozello.shop/gry/params/post/5141394/mm6</link>
                <pubDate>Thu, 02 Oct 2025 10:30:00 +0000</pubDate>
                <description>рррррррррррррррррррррр&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;6&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;



    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Мозаїка Майстрів — Версія 1.9&lt;/title&gt;
    &lt;style&gt;
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
            padding: 10px;
            background-color: #f0f0f0;
            font-family: Arial, sans-serif;
            overflow: auto;
        }

        #mainGameContainer {
            display: flex;
            align-items: flex-start;
            justify-content: center;
            gap: 20px;
            margin-top: 20px;
        }

        #gridContainer {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        #gameCanvas {
            border: 2px solid #333;
            background-color: #e3f1c6;
            max-width: 100%;
            height: auto;
        }

        #nextBlocks {
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
            margin-top: 0;
            flex-wrap: nowrap;
            width: auto;
            max-width: 100px;
            gap: 10px;
        }

        .blockCanvas {
            border: 1px solid #ccc;
            cursor: grab;
            width: 80px;
            height: 80px;
            margin: 0;
        }

        .blockCanvas.dragging {
            opacity: 0.5;
            cursor: grabbing;
        }

        #score, #highScore {
            font-size: 20px;
            margin-top: 10px;
        }

        #bonusMessage {
            display: none;
            position: fixed;
            top: 20%;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(0, 128, 0, 0.8);
            color: white;
            padding: 10px 20px;
            border-radius: 5px;
            z-index: 1000;
            font-size: 18px;
        }

        #gameOver, #pauseOverlay {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 15px;
            border-radius: 10px;
            text-align: center;
            z-index: 1000;
        }

        button {
            margin-top: 10px;
            padding: 8px 16px;
            font-size: 14px;
            cursor: pointer;
        }

        h2 {
            margin: 10px 0;
        }

        p {
            margin: 5px 0;
        }

        .accordion {
            width: 100%;
            max-width: 500px;
            margin-top: 20px;
        }

        .accordion-item {
            border: 1px solid #333;
            margin-bottom: 5px;
            border-radius: 5px;
        }

        .accordion-header {
            background-color: #ddd;
            padding: 10px;
            cursor: pointer;
            font-size: 18px;
            font-weight: bold;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .accordion-header::after {
            content: &#039;▼&#039;;
            font-size: 14px;
        }

        .accordion-header.active::after {
            content: &#039;▲&#039;;
        }

        .accordion-content {
            display: none;
            padding: 10px;
            background-color: #fff;
        }

        .accordion-content.active {
            display: block;
        }

        .accordion-content table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 15px;
        }

        .accordion-content th, .accordion-content td {
            border: 1px solid #333;
            padding: 8px;
            text-align: center;
        }

        .accordion-content th {
            background-color: #ddd;
        }

        .accordion-content pre {
            margin: 0;
            font-size: 12px;
        }

        .accordion-content canvas {
            border: 1px solid #ccc;
        }
    &lt;/style&gt;


    &lt;h2&gt;Мозаїка Майстрів — Версія 1.9&lt;/h2&gt;
    &lt;p&gt;Права кнопка миші — поворот блоку, Середня кнопка/подвійне торкання — перевертання, Кнопка &quot;Скасувати&quot; — скасування ходу&lt;/p&gt;

    &lt;div id=&quot;mainGameContainer&quot;&gt;
        &lt;div id=&quot;gridContainer&quot;&gt;
            &lt;canvas id=&quot;gameCanvas&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&lt;/canvas&gt;
            &lt;button id=&quot;pauseButton&quot; fdprocessedid=&quot;62619d&quot;&gt;Пауза&lt;/button&gt;
            &lt;button id=&quot;undoButton&quot; disabled=&quot;&quot;&gt;Скасувати&lt;/button&gt;
            &lt;div id=&quot;score&quot;&gt;Очки: 0&lt;/div&gt;
            &lt;div id=&quot;highScore&quot;&gt;Рекорд: 0&lt;/div&gt;
        &lt;/div&gt;
        &lt;div id=&quot;nextBlocks&quot;&gt;
            &lt;canvas id=&quot;block1&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
            &lt;canvas id=&quot;block2&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
            &lt;canvas id=&quot;block3&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div id=&quot;bonusMessage&quot;&gt;&lt;/div&gt;
    &lt;div id=&quot;gameOver&quot;&gt;
        &lt;h2&gt;Гра закінчена!&lt;/h2&gt;
        &lt;p id=&quot;finalScore&quot;&gt;&lt;/p&gt;
        &lt;button onclick=&quot;restartGame()&quot;&gt;Грати знову&lt;/button&gt;
    &lt;/div&gt;
    &lt;div id=&quot;pauseOverlay&quot;&gt;
        &lt;h2&gt;Гра на паузі&lt;/h2&gt;
        &lt;button onclick=&quot;togglePause()&quot;&gt;Відновити&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion&quot;&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Таблиця блоків&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;table&gt;
                    &lt;thead&gt;
                        &lt;tr&gt;
                            &lt;th&gt;Назва&lt;/th&gt;
                            &lt;th&gt;Зображення&lt;/th&gt;
                            &lt;th&gt;Структура&lt;/th&gt;
                            &lt;th&gt;Використання&lt;/th&gt;
                        &lt;/tr&gt;
                    &lt;/thead&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Одинарний&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSingle&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення окремих клітинок&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;L-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeL&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для кутів або вузьких просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;T-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeT&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1],&lt;br&gt;[0, 1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для горизонтальних ліній з виступом&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (4)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI4&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Квадрат&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSquare&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для компактних квадратних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Z-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeZ&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 0],&lt;br&gt;[0, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для зміщених &quot;змійок&quot;&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (5)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI5&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (3)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для середніх рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (2)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для коротких рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 2x2&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0],&lt;br&gt;[0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення діагональних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 3x3&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0, 0],&lt;br&gt;[0, 1, 0],&lt;br&gt;[0, 0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих діагональних ліній&lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                &lt;/table&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Інструкція&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;h3&gt;Мета гри&lt;/h3&gt;
                &lt;p&gt;&quot;Мозаїка Майстрів&quot; — це головоломка, де гравець розміщує блоки на сітці 10x10, щоб очищати цілі рядки або стовпці. Мета — набрати якомога більше очок і встановити рекорд. Гра закінчується, коли жоден блок не можна розмістити.&lt;/p&gt;
                
                &lt;h3&gt;Правила гри&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Ігрове поле&lt;/b&gt;: Сітка 10x10, де клітинки можуть бути порожніми або заповненими.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Черга блоків&lt;/b&gt;: До трьох блоків відображаються справа для розміщення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Розміщення&lt;/b&gt;: Перетягуйте блоки на сітку. Розміщення можливе лише у вільних місцях.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Очищення ліній&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;Повний рядок або стовпець очищається.&lt;/li&gt;
                            &lt;li&gt;1 лінія: 100 очок.&lt;/li&gt;
                            &lt;li&gt;2+ ліній: 100 + 50 за кожну додаткову (наприклад, 2 лінії = 150 очок).&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Бонус за очищення поля&lt;/b&gt;: 25% від суми очок, якщо поле порожнє.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Рекорд&lt;/b&gt;: Зберігається у браузері, відображається під час гри та після завершення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Кінець гри&lt;/b&gt;: Гра закінчується, якщо блоки неможливо розмістити.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Дії гравця&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Перетягування&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;ПК: Лівою кнопкою миші.&lt;/li&gt;
                            &lt;li&gt;Сенсорні пристрої: Торкніться та перетягніть.&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Поворот&lt;/b&gt;: Права кнопка миші або довге натискання (300мс).&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Перевертання&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;ПК: Середня кнопка миші або подвійне клацання.&lt;/li&gt;
                            &lt;li&gt;Сенсорні пристрої: Двохпальцевий тап.&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Скасування ходу&lt;/b&gt;: Кнопка &quot;Скасувати&quot; для останнього ходу.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Пауза&lt;/b&gt;: Кнопка &quot;Пауза&quot;/&quot;Відновити&quot;.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Перезапуск&lt;/b&gt;: Кнопка &quot;Грати знову&quot; на екрані &quot;Гра закінчена&quot;.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Поради&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;Плануйте ходи, щоб створювати повні лінії.&lt;/li&gt;
                    &lt;li&gt;Використовуйте одинарний блок для прогалин.&lt;/li&gt;
                    &lt;li&gt;Скасовуйте невдалі ходи.&lt;/li&gt;
                    &lt;li&gt;Намагайтеся очищати кілька ліній для бонусів.&lt;/li&gt;
                    &lt;li&gt;Експериментуйте з діагональними блоками для унікальних комбінацій.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;script&gt;
        // Акордеон-меню
        function toggleAccordion(header) {
            const content = header.nextElementSibling;
            const isActive = content.classList.contains(&#039;active&#039;);
            document.querySelectorAll(&#039;.accordion-content&#039;).forEach(item =&gt; {
                item.classList.remove(&#039;active&#039;);
                item.previousElementSibling.classList.remove(&#039;active&#039;);
            });
            if (!isActive) {
                content.classList.add(&#039;active&#039;);
                header.classList.add(&#039;active&#039;);
            }
        }

        // Ігрова логіка
        const gameCanvas = document.getElementById(&#039;gameCanvas&#039;);
        const ctx = gameCanvas.getContext(&#039;2d&#039;);
        const gridSize = 10;
        const cellSize = gameCanvas.width / gridSize;
        const scoreElement = document.getElementById(&#039;score&#039;);
        const highScoreElement = document.getElementById(&#039;highScore&#039;);
        const bonusMessageElement = document.getElementById(&#039;bonusMessage&#039;);
        const gameOverElement = document.getElementById(&#039;gameOver&#039;);
        const finalScoreElement = document.getElementById(&#039;finalScore&#039;);
        const pauseButton = document.getElementById(&#039;pauseButton&#039;);
        const undoButton = document.getElementById(&#039;undoButton&#039;);
        const pauseOverlay = document.getElementById(&#039;pauseOverlay&#039;);

        let grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
        let score = 0;
        let highScore = parseInt(localStorage.getItem(&#039;blockLegendHighScore&#039;)) || 0;
        let currentBlocks = [];
        let selectedBlock = null;
        let gameActive = true;
        let gamePaused = false;
        let lastMove = null;

        highScoreElement.textContent = `Рекорд: ${highScore}`;
        console.log(&#039;Завантажено рекорд:&#039;, highScore);

        const blockShapes = [
            [[1]], // Одинарний (1x1)
            [[1]], // Одинарний (збільшена ймовірність)
            [[1, 1], [1, 0]], // L-форма
            [[1, 1, 1], [0, 1, 0]], // T-форма
            [[1, 1, 1, 1]], // I-форма (4)
            [[1, 1], [1, 1]], // Квадрат
            [[1, 1, 0], [0, 1, 1]], // Z-форма
            [[1, 1, 1, 1, 1]], // I-форма (5)
            [[1, 1, 1]], // I-форма (3)
            [[1, 1]], // I-форма (2)
            [[1, 0], [0, 1]], // Діагональ 2x2
            [[1, 0, 0], [0, 1, 0], [0, 0, 1]] // Діагональ 3x3
        ];

        const colors = [&#039;#FF0000&#039;, &#039;#00FF00&#039;, &#039;#0000FF&#039;, &#039;#FFFF00&#039;, &#039;#FF00FF&#039;, &#039;#FFA500&#039;, &#039;#800080&#039;, &#039;#00FFFF&#039;, &#039;#FF4500&#039;, &#039;#2E8B57&#039;, &#039;#DAA520&#039;, &#039;#8A2BE2&#039;];

        // Малювання блоків у таблиці
        function drawTableBlock(canvasId, shape, color) {
            const canvas = document.getElementById(canvasId);
            const ctx = canvas.getContext(&#039;2d&#039;);
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            shape.forEach((row, y) =&gt; {
                row.forEach((cell, x) =&gt; {
                    if (cell) {
                        ctx.fillStyle = color;
                        ctx.fillRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        ctx.strokeStyle = &#039;#000&#039;;
                        ctx.strokeRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                });
            });
        }

        // Ініціалізація малюнків у таблиці
        drawTableBlock(&#039;shapeSingle&#039;, blockShapes[0], colors[0]);
        drawTableBlock(&#039;shapeL&#039;, blockShapes[2], colors[1]);
        drawTableBlock(&#039;shapeT&#039;, blockShapes[3], colors[2]);
        drawTableBlock(&#039;shapeI4&#039;, blockShapes[4], colors[3]);
        drawTableBlock(&#039;shapeSquare&#039;, blockShapes[5], colors[4]);
        drawTableBlock(&#039;shapeZ&#039;, blockShapes[6], colors[0]);
        drawTableBlock(&#039;shapeI5&#039;, blockShapes[7], colors[5]);
        drawTableBlock(&#039;shapeI3&#039;, blockShapes[8], colors[6]);
        drawTableBlock(&#039;shapeI2&#039;, blockShapes[9], colors[1]);
        drawTableBlock(&#039;shapeDiagonal2&#039;, blockShapes[10], colors[10]);
        drawTableBlock(&#039;shapeDiagonal3&#039;, blockShapes[11], colors[11]);

        function generateBlocks() {
            currentBlocks = [];
            for (let i = 0; i &lt; 3; i++) {
                const shapeIndex = Math.floor(Math.random() * blockShapes.length);
                const shape = blockShapes[shapeIndex];
                const colorIndex = Math.floor(Math.random() * colors.length);
                currentBlocks.push({ shape: shape, color: colors[colorIndex] });
                drawBlock(i, shape, colors[colorIndex]);
            }
        }

        function drawBlock(index, shape, color) {
            const canvas = document.getElementById(`block${index + 1}`);
            const blockCtx = canvas.getContext(&#039;2d&#039;);
            blockCtx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            const offsetX = (canvas.width - (shape[0].length * blockCellSize)) / 2;
            const offsetY = (canvas.height - (shape.length * blockCellSize)) / 2;
            shape.forEach((row, y) =&gt; {
                row.forEach((cell, x) =&gt; {
                    if (cell) {
                        blockCtx.fillStyle = color;
                        blockCtx.fillRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        blockCtx.strokeStyle = &#039;#000&#039;;
                        blockCtx.strokeRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                });
            });
        }

        function rotateShape(shape) {
            const rows = shape.length;
            const cols = shape[0].length;
            const rotated = Array(cols).fill().map(() =&gt; Array(rows).fill(0));
            for (let y = 0; y &lt; rows; y++) {
                for (let x = 0; x &lt; cols; x++) {
                    rotated[x][rows - 1 - y] = shape[y][x];
                }
            }
            return rotated;
        }

        function flipShape(shape) {
            return shape.map(row =&gt; [...row].reverse());
        }

        function showBonusMessage(message) {
            bonusMessageElement.textContent = message;
            bonusMessageElement.style.display = &#039;block&#039;;
            setTimeout(() =&gt; bonusMessageElement.style.display = &#039;none&#039;, 2000);
        }

        function drawGrid() {
            ctx.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
            for (let y = 0; y &lt; gridSize; y++) {
                for (let x = 0; x &lt; gridSize; x++) {
                    ctx.strokeStyle = &#039;#000&#039;;
                    ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize);
                    if (grid[y][x]) {
                        ctx.fillStyle = grid[y][x];
                        ctx.fillRect(x * cellSize + 2, y * cellSize + 2, cellSize - 4, cellSize - 4);
                    }
                }
            }
        }

        function drawPreview(shape, x, y, valid) {
            drawGrid();
            if (shape &amp;&amp; x &gt;= 0 &amp;&amp; y &gt;= 0) {
                ctx.globalAlpha = 0.5;
                for (let sy = 0; sy &lt; shape.length; sy++) {
                    for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                        if (shape[sy][sx]) {
                            ctx.fillStyle = valid ? selectedBlock.color : &#039;#FF0000&#039;;
                            ctx.fillRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                            ctx.strokeStyle = &#039;#000&#039;;
                            ctx.strokeRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                        }
                    }
                }
                ctx.globalAlpha = 1.0;
            }
        }

        function canPlaceBlock(shape, x, y) {
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        const gridX = x + sx;
                        const gridY = y + sy;
                        if (gridX &lt; 0 || gridX &gt;= gridSize || gridY &lt; 0 || gridY &gt;= gridSize || grid[gridY][gridX]) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        function placeBlock(shape, color, x, y, blockIndex) {
            console.log(`Розміщення блоку на позиції (${x}, ${y}), індекс: ${blockIndex}, форма:`, JSON.stringify(shape));
            lastMove = {
                grid: grid.map(row =&gt; [...row]),
                score,
                block: { shape, color },
                blockIndex
            };
            undoButton.disabled = false;
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        grid[y + sy][x + sx] = color;
                    }
                }
            }
            console.log(&#039;Блок розміщено, викликаємо checkLines&#039;);
            checkLines();
            console.log(&#039;checkLines завершено, викликаємо checkGameOver&#039;);
            checkGameOver();
            drawGrid();
            console.log(&#039;Розміщення завершено, поточна черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
        }

        function checkLines() {
            let linesCleared = 0;
            for (let y = gridSize - 1; y &gt;= 0; y--) {
                if (grid[y].every(cell =&gt; cell)) {
                    grid.splice(y, 1);
                    grid.unshift(Array(gridSize).fill(null));
                    linesCleared++;
                    y++;
                }
            }
            for (let x = gridSize - 1; x &gt;= 0; x--) {
                let isFull = true;
                for (let y = 0; y &lt; gridSize; y++) {
                    if (!grid[y][x]) {
                        isFull = false;
                        break;
                    }
                }
                if (isFull) {
                    for (let y = 0; y &lt; gridSize; y++) {
                        grid[y].splice(x, 1);
                        grid[y].push(null);
                    }
                    linesCleared++;
                    x++;
                }
            }
            if (linesCleared &gt; 0) {
                let lineBonus = linesCleared === 1 ? 100 : 100 + (linesCleared - 1) * 50;
                score += lineBonus;
                if (linesCleared &gt; 1) {
                    showBonusMessage(`Бонус за ${linesCleared} лінії: +${lineBonus} очок`);
                    console.log(`Бонус за очищення ${linesCleared} ліній: +${lineBonus} очок`);
                }
                const isGridEmpty = grid.every(row =&gt; row.every(cell =&gt; !cell));
                if (isGridEmpty &amp;&amp; score &gt; 0) {
                    const clearBonus = Math.floor(score * 0.25);
                    score += clearBonus;
                    showBonusMessage(`Бонус за повне очищення поля: +${clearBonus} очок`);
                    console.log(`Бонус за повне очищення поля: +${clearBonus} очок`);
                }
                scoreElement.textContent = `Очки: ${score}`;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    highScoreElement.textContent = `Рекорд: ${highScore}`;
                    console.log(&#039;Новий рекорд:&#039;, highScore);
                }
            }
            console.log(&#039;Очищено ліній:&#039;, linesCleared, &#039;Очки:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function checkGameOver() {
            console.log(&#039;Перевірка стану гри. Кількість блоків:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
            if (currentBlocks.length === 0) {
                console.log(&#039;Черга порожня, генеруємо нові блоки&#039;);
                setTimeout(() =&gt; {
                    generateBlocks();
                    console.log(&#039;Нові блоки згенеровано, нова черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                }, 0);
                return;
            }
            let canPlaceAny = false;
            for (let block of currentBlocks) {
                for (let y = 0; y &lt; gridSize; y++) {
                    for (let x = 0; x &lt; gridSize; x++) {
                        if (canPlaceBlock(block.shape, x, y)) {
                            canPlaceAny = true;
                            break;
                        }
                    }
                    if (canPlaceAny) break;
                }
                if (canPlaceAny) break;
            }
            console.log(&#039;Чи можна розмістити блок:&#039;, canPlaceAny);
            if (!canPlaceAny) {
                gameActive = false;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    console.log(&#039;Новий рекорд на кінці гри:&#039;, highScore);
                }
                finalScoreElement.textContent = `Ваш рахунок: ${score}\nРекорд: ${highScore}`;
                gameOverElement.style.display = &#039;block&#039;;
                console.log(&#039;Гра закінчена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
            }
        }

        function restartGame() {
            grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
            score = 0;
            scoreElement.textContent = `Очки: ${score}`;
            highScoreElement.textContent = `Рекорд: ${highScore}`;
            gameOverElement.style.display = &#039;none&#039;;
            gamePaused = false;
            pauseButton.textContent = &#039;Пауза&#039;;
            pauseOverlay.style.display = &#039;none&#039;;
            undoButton.disabled = true;
            lastMove = null;
            gameActive = true;
            currentBlocks = [];
            generateBlocks();
            drawGrid();
            console.log(&#039;Гра перезапущена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function undoMove() {
            if (!lastMove || !gameActive || gamePaused) return;
            grid = lastMove.grid.map(row =&gt; [...row]);
            score = lastMove.score;
            currentBlocks.splice(lastMove.blockIndex, 0, lastMove.block);
            scoreElement.textContent = `Очки: ${score}`;
            undoButton.disabled = true;
            lastMove = null;
            for (let i = 0; i &lt; 3; i++) {
                const blockCanvas = document.getElementById(`block${i + 1}`);
                blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                if (i &lt; currentBlocks.length) {
                    drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                }
            }
            drawGrid();
            console.log(&#039;Хід скасовано. Поточна черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
        }

        function togglePause() {
            if (!gameActive) return;
            gamePaused = !gamePaused;
            pauseButton.textContent = gamePaused ? &#039;Відновити&#039; : &#039;Пауза&#039;;
            pauseOverlay.style.display = gamePaused ? &#039;block&#039; : &#039;none&#039;;
            console.log(&#039;Гра на паузі:&#039;, gamePaused);
        }

        pauseButton.addEventListener(&#039;click&#039;, togglePause);
        undoButton.addEventListener(&#039;click&#039;, undoMove);

        let touchStartX = 0;
        let touchStartY = 0;
        const blockCanvases = document.querySelectorAll(&#039;.blockCanvas&#039;);
        blockCanvases.forEach(canvas =&gt; {
            canvas.addEventListener(&#039;dragstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                selectedBlock = currentBlocks[index];
                canvas.classList.add(&#039;dragging&#039;);
                e.dataTransfer.setData(&#039;text/plain&#039;, index);
                console.log(&#039;Початок перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
            });

            canvas.addEventListener(&#039;dragend&#039;, (e) =&gt; {
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Кінець перетягування&#039;);
            });

            canvas.addEventListener(&#039;contextmenu&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                currentBlocks[index].shape = rotateShape(currentBlocks[index].shape);
                drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                console.log(&#039;Блок повернуто:&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
            });

            canvas.addEventListener(&#039;mousedown&#039;, (e) =&gt; {
                if (e.button === 1) {
                    e.preventDefault();
                    if (!gameActive || gamePaused) return;
                    const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (середня кнопка):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });

            canvas.addEventListener(&#039;dblclick&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (подвійне клацання):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });

            canvas.addEventListener(&#039;touchstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    selectedBlock = currentBlocks[index];
                    canvas.classList.add(&#039;dragging&#039;);

                    // Record initial touch position for movement tolerance
                    const touch = e.touches[0];
                    touchStartX = touch.clientX;
                    touchStartY = touch.clientY;

                    // Two-finger tap detection for flipping
                    if (e.touches.length === 2) {
                        const touch1 = e.touches[0];
                        const touch2 = e.touches[1];
                        const moveTolerance = 10; // Pixels of movement allowed
                        const dx1 = Math.abs(touch1.clientX - touchStartX);
                        const dy1 = Math.abs(touch1.clientY - touchStartY);
                        const dx2 = Math.abs(touch2.clientX - touchStartX);
                        const dy2 = Math.abs(touch2.clientY - touchStartY);
                        if (dx1 &lt; moveTolerance &amp;&amp; dy1 &lt; moveTolerance &amp;&amp; dx2 &lt; moveTolerance &amp;&amp; dy2 &lt; moveTolerance) {
                            currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                            drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                            console.log(&#039;Блок перевернуто (двохпальцевий тап):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                            e.preventDefault(); // Prevent default behavior (e.g., zoom)
                        }
                        return; // Exit early to avoid long-press interference
                    }

                    // Long-press detection for rotation
                    let touchStartTime = Date.now();
                    const touchHoldTimeout = setTimeout(() =&gt; {
                        if (Date.now() - touchStartTime &gt;= 300 &amp;&amp; e.touches.length === 1) { // Reduced to 300ms
                            currentBlocks[index].shape = rotateShape(currentBlocks[index].shape);
                            drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                            console.log(&#039;Блок повернуто (довге натискання):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                        }
                    }, 300);

                    // Cancel timeout on touchend or touchmove
                    const touchEndOrMove = (event) =&gt; {
                        const currentTouch = event.touches[0] || event.changedTouches[0];
                        const dx = Math.abs(currentTouch.clientX - touchStartX);
                        const dy = Math.abs(currentTouch.clientY - touchStartY);
                        if (dx &gt; 10 || dy &gt; 10) { // Cancel if significant movement
                            clearTimeout(touchHoldTimeout);
                        }
                    };
                    canvas.addEventListener(&#039;touchend&#039;, touchEndOrMove, { once: true });
                    canvas.addEventListener(&#039;touchmove&#039;, touchEndOrMove, { once: true });

                    console.log(&#039;Початок сенсорного перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
                } else {
                    console.error(&#039;Помилка: невалідний індекс блоку на touchstart&#039;, index);
                }
            });

            canvas.addEventListener(&#039;touchmove&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.touches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                const valid = canPlaceBlock(selectedBlock.shape, x, y);
                drawPreview(selectedBlock.shape, x, y, valid);
            });

            canvas.addEventListener(&#039;touchend&#039;, (e) =&gt; {
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.changedTouches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                console.log(`Сенсорне розміщення: координати (${x}, ${y}), індекс: ${index}, блок:`, JSON.stringify(selectedBlock));
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    if (canPlaceBlock(selectedBlock.shape, x, y)) {
                        placeBlock(selectedBlock.shape, selectedBlock.color, x, y, index);
                        currentBlocks.splice(index, 1);
                        console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                        for (let i = 0; i &lt; 3; i++) {
                            const blockCanvas = document.getElementById(`block${i + 1}`);
                            blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                            if (i &lt; currentBlocks.length) {
                                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                            }
                        }
                        checkGameOver();
                        selectedBlock = null;
                    } else {
                        console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                    }
                } else {
                    console.error(&#039;Помилка: невалідний індекс блоку на touchend&#039;, index);
                }
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Сенсорне розміщення завершено&#039;);
            });
        });

        generateBlocks();
        drawGrid();
        console.log(&#039;Гра ініціалізована — Мозаїка Майстрів Версія 1.9&#039;);
    &lt;/script&gt;</description>
            </item>
                    <item>
                <title>Мозаїка Майстрів</title>
                <link>http://margo.mozello.shop/gry/params/post/5141333/mozaka-majstrv</link>
                <pubDate>Thu, 02 Oct 2025 09:25:00 +0000</pubDate>
                <description>ооооооооооооооооооооооооо&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;15&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;



    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Мозаїка Майстрів — Версія 1.9&lt;/title&gt;
    &lt;style&gt;
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
            padding: 10px;
            background-color: #f0f0f0;
            font-family: Arial, sans-serif;
            overflow: auto;
        }

        #mainGameContainer {
            display: flex;
            align-items: flex-start;
            justify-content: center;
            gap: 20px;
            margin-top: 20px;
        }

        #gridContainer {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        #gameCanvas {
            border: 2px solid #333;
            background-color: #e3f1c6;
            max-width: 100%;
            height: auto;
        }

        #nextBlocks {
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
            margin-top: 0;
            flex-wrap: nowrap;
            width: auto;
            max-width: 100px;
            gap: 10px;
        }

        .blockCanvas {
            border: 1px solid #ccc;
            cursor: grab;
            width: 80px;
            height: 80px;
            margin: 0;
        }

        .blockCanvas.dragging {
            opacity: 0.5;
            cursor: grabbing;
        }

        #score, #highScore {
            font-size: 20px;
            margin-top: 10px;
        }

        #bonusMessage {
            display: none;
            position: fixed;
            top: 20%;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(0, 128, 0, 0.8);
            color: white;
            padding: 10px 20px;
            border-radius: 5px;
            z-index: 1000;
            font-size: 18px;
        }

        #gameOver, #pauseOverlay {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 15px;
            border-radius: 10px;
            text-align: center;
            z-index: 1000;
        }

        button {
            margin-top: 10px;
            padding: 8px 16px;
            font-size: 14px;
            cursor: pointer;
        }

        h2 {
            margin: 10px 0;
        }

        p {
            margin: 5px 0;
        }

        .accordion {
            width: 100%;
            max-width: 500px;
            margin-top: 20px;
        }

        .accordion-item {
            border: 1px solid #333;
            margin-bottom: 5px;
            border-radius: 5px;
        }

        .accordion-header {
            background-color: #ddd;
            padding: 10px;
            cursor: pointer;
            font-size: 18px;
            font-weight: bold;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .accordion-header::after {
            content: &#039;▼&#039;;
            font-size: 14px;
        }

        .accordion-header.active::after {
            content: &#039;▲&#039;;
        }

        .accordion-content {
            display: none;
            padding: 10px;
            background-color: #fff;
        }

        .accordion-content.active {
            display: block;
        }

        .accordion-content table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 15px;
        }

        .accordion-content th, .accordion-content td {
            border: 1px solid #333;
            padding: 8px;
            text-align: center;
        }

        .accordion-content th {
            background-color: #ddd;
        }

        .accordion-content pre {
            margin: 0;
            font-size: 12px;
        }

        .accordion-content canvas {
            border: 1px solid #ccc;
        }
    &lt;/style&gt;


    &lt;h2&gt;Мозаїка Майстрів — Версія 1.9&lt;/h2&gt;
    &lt;p&gt;Права кнопка миші — поворот блоку, Середня кнопка/подвійне торкання — перевертання, Кнопка &quot;Скасувати&quot; — скасування ходу&lt;/p&gt;

    &lt;div id=&quot;mainGameContainer&quot; style=&quot;display: flex; align-items: flex-start; justify-content: center; gap: 20px;&quot;&gt;
        &lt;div id=&quot;gridContainer&quot;&gt;
            &lt;canvas id=&quot;gameCanvas&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&lt;/canvas&gt;
            &lt;button id=&quot;pauseButton&quot;&gt;Пауза&lt;/button&gt;
            &lt;button id=&quot;undoButton&quot; disabled=&quot;&quot;&gt;Скасувати&lt;/button&gt;
            &lt;div id=&quot;score&quot;&gt;Очки: 0&lt;/div&gt;
            &lt;div id=&quot;highScore&quot;&gt;Рекорд: 0&lt;/div&gt;
        &lt;/div&gt;
        &lt;div id=&quot;nextBlocks&quot;&gt;
            &lt;canvas id=&quot;block1&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
            &lt;canvas id=&quot;block2&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
            &lt;canvas id=&quot;block3&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div id=&quot;bonusMessage&quot;&gt;&lt;/div&gt;
    &lt;div id=&quot;gameOver&quot;&gt;
        &lt;h2&gt;Гра закінчена!&lt;/h2&gt;
        &lt;p id=&quot;finalScore&quot;&gt;&lt;/p&gt;
        &lt;button onclick=&quot;restartGame()&quot;&gt;Грати знову&lt;/button&gt;
    &lt;/div&gt;
    &lt;div id=&quot;pauseOverlay&quot;&gt;
        &lt;h2&gt;Гра на паузі&lt;/h2&gt;
        &lt;button onclick=&quot;togglePause()&quot;&gt;Відновити&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion&quot;&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Таблиця блоків&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;table&gt;
                    &lt;thead&gt;
                        &lt;tr&gt;
                            &lt;th&gt;Назва&lt;/th&gt;
                            &lt;th&gt;Зображення&lt;/th&gt;
                            &lt;th&gt;Структура&lt;/th&gt;
                            &lt;th&gt;Використання&lt;/th&gt;
                        &lt;/tr&gt;
                    &lt;/thead&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Одинарний&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSingle&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення окремих клітинок&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;L-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeL&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для кутів або вузьких просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;T-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeT&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1],&lt;br&gt;[0, 1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для горизонтальних ліній з виступом&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (4)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI4&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Квадрат&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSquare&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для компактних квадратних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Z-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeZ&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 0],&lt;br&gt;[0, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для зміщених &quot;змійок&quot;&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (5)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI5&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (3)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для середніх рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (2)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для коротких рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 2x2&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0],&lt;br&gt;[0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення діагональних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 3x3&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0, 0],&lt;br&gt;[0, 1, 0],&lt;br&gt;[0, 0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих діагональних ліній&lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                &lt;/table&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Інструкція&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;h3&gt;Мета гри&lt;/h3&gt;
                &lt;p&gt;&quot;Мозаїка Майстрів&quot; — це головоломка, де гравець розміщує блоки на сітці 10x10, щоб очищати цілі рядки або стовпці. Мета — набрати якомога більше очок і встановити рекорд. Гра закінчується, коли жоден блок не можна розмістити.&lt;/p&gt;
                
                &lt;h3&gt;Правила гри&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Ігрове поле&lt;/b&gt;: Сітка 10x10, де клітинки можуть бути порожніми або заповненими.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Черга блоків&lt;/b&gt;: До трьох блоків відображаються справа для розміщення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Розміщення&lt;/b&gt;: Перетягуйте блоки на сітку. Розміщення можливе лише у вільних місцях.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Очищення ліній&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;Повний рядок або стовпець очищається.&lt;/li&gt;
                            &lt;li&gt;1 лінія: 100 очок.&lt;/li&gt;
                            &lt;li&gt;2+ ліній: 100 + 50 за кожну додаткову (наприклад, 2 лінії = 150 очок).&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Бонус за очищення поля&lt;/b&gt;: 25% від суми очок, якщо поле порожнє.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Рекорд&lt;/b&gt;: Зберігається у браузері, відображається під час гри та після завершення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Кінець гри&lt;/b&gt;: Гра закінчується, якщо блоки неможливо розмістити.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Дії гравця&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Перетягування&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;ПК: Лівою кнопкою миші.&lt;/li&gt;
                            &lt;li&gt;Сенсорні пристрої: Торкніться та перетягніть.&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Поворот&lt;/b&gt;: Права кнопка миші (90°).&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Перевертання&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;ПК: Середня кнопка миші або подвійне клацання.&lt;/li&gt;
                            &lt;li&gt;Сенсорні пристрої: Подвійне торкання.&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Скасування ходу&lt;/b&gt;: Кнопка &quot;Скасувати&quot; для останнього ходу.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Пауза&lt;/b&gt;: Кнопка &quot;Пауза&quot;/&quot;Відновити&quot;.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Перезапуск&lt;/b&gt;: Кнопка &quot;Грати знову&quot; на екрані &quot;Гра закінчена&quot;.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Поради&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;Плануйте ходи, щоб створювати повні лінії.&lt;/li&gt;
                    &lt;li&gt;Використовуйте одинарний блок для прогалин.&lt;/li&gt;
                    &lt;li&gt;Скасовуйте невдалі ходи.&lt;/li&gt;
                    &lt;li&gt;Намагайтеся очищати кілька ліній для бонусів.&lt;/li&gt;
                    &lt;li&gt;Експериментуйте з діагональними блоками для унікальних комбінацій.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;script&gt;
        // Акордеон-меню
        function toggleAccordion(header) {
            const content = header.nextElementSibling;
            const isActive = content.classList.contains(&#039;active&#039;);
            document.querySelectorAll(&#039;.accordion-content&#039;).forEach(item =&gt; {
                item.classList.remove(&#039;active&#039;);
                item.previousElementSibling.classList.remove(&#039;active&#039;);
            });
            if (!isActive) {
                content.classList.add(&#039;active&#039;);
                header.classList.add(&#039;active&#039;);
            }
        }

        // Ігрова логіка
        const gameCanvas = document.getElementById(&#039;gameCanvas&#039;);
        const ctx = gameCanvas.getContext(&#039;2d&#039;);
        const gridSize = 10;
        const cellSize = gameCanvas.width / gridSize;
        const scoreElement = document.getElementById(&#039;score&#039;);
        const highScoreElement = document.getElementById(&#039;highScore&#039;);
        const bonusMessageElement = document.getElementById(&#039;bonusMessage&#039;);
        const gameOverElement = document.getElementById(&#039;gameOver&#039;);
        const finalScoreElement = document.getElementById(&#039;finalScore&#039;);
        const pauseButton = document.getElementById(&#039;pauseButton&#039;);
        const undoButton = document.getElementById(&#039;undoButton&#039;);
        const pauseOverlay = document.getElementById(&#039;pauseOverlay&#039;);

        let grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
        let score = 0;
        let highScore = parseInt(localStorage.getItem(&#039;blockLegendHighScore&#039;)) || 0;
        let currentBlocks = [];
        let selectedBlock = null;
        let gameActive = true;
        let gamePaused = false;
        let lastMove = null;

        highScoreElement.textContent = `Рекорд: ${highScore}`;
        console.log(&#039;Завантажено рекорд:&#039;, highScore);

        const blockShapes = [
            [[1]], // Одинарний (1x1)
            [[1]], // Одинарний (збільшена ймовірність)
            [[1, 1], [1, 0]], // L-форма
            [[1, 1, 1], [0, 1, 0]], // T-форма
            [[1, 1, 1, 1]], // I-форма (4)
            [[1, 1], [1, 1]], // Квадрат
            [[1, 1, 0], [0, 1, 1]], // Z-форма
            [[1, 1, 1, 1, 1]], // I-форма (5)
            [[1, 1, 1]], // I-форма (3)
            [[1, 1]], // I-форма (2)
            [[1, 0], [0, 1]], // Діагональ 2x2
            [[1, 0, 0], [0, 1, 0], [0, 0, 1]] // Діагональ 3x3
        ];

        const colors = [&#039;#FF0000&#039;, &#039;#00FF00&#039;, &#039;#0000FF&#039;, &#039;#FFFF00&#039;, &#039;#FF00FF&#039;, &#039;#FFA500&#039;, &#039;#800080&#039;, &#039;#00FFFF&#039;, &#039;#FF4500&#039;, &#039;#2E8B57&#039;, &#039;#DAA520&#039;, &#039;#8A2BE2&#039;];

        // Малювання блоків у таблиці
        function drawTableBlock(canvasId, shape, color) {
            const canvas = document.getElementById(canvasId);
            const ctx = canvas.getContext(&#039;2d&#039;);
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            shape.forEach((row, y) =&gt; {
                row.forEach((cell, x) =&gt; {
                    if (cell) {
                        ctx.fillStyle = color;
                        ctx.fillRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        ctx.strokeStyle = &#039;#000&#039;;
                        ctx.strokeRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                });
            });
        }

        // Ініціалізація малюнків у таблиці
        drawTableBlock(&#039;shapeSingle&#039;, blockShapes[0], colors[0]);
        drawTableBlock(&#039;shapeL&#039;, blockShapes[2], colors[1]);
        drawTableBlock(&#039;shapeT&#039;, blockShapes[3], colors[2]);
        drawTableBlock(&#039;shapeI4&#039;, blockShapes[4], colors[3]);
        drawTableBlock(&#039;shapeSquare&#039;, blockShapes[5], colors[4]);
        drawTableBlock(&#039;shapeZ&#039;, blockShapes[6], colors[0]);
        drawTableBlock(&#039;shapeI5&#039;, blockShapes[7], colors[5]);
        drawTableBlock(&#039;shapeI3&#039;, blockShapes[8], colors[6]);
        drawTableBlock(&#039;shapeI2&#039;, blockShapes[9], colors[1]);
        drawTableBlock(&#039;shapeDiagonal2&#039;, blockShapes[10], colors[10]);
        drawTableBlock(&#039;shapeDiagonal3&#039;, blockShapes[11], colors[11]);

        function generateBlocks() {
            currentBlocks = [];
            for (let i = 0; i &lt; 3; i++) {
                const shapeIndex = Math.floor(Math.random() * blockShapes.length);
                const shape = blockShapes[shapeIndex];
                const colorIndex = Math.floor(Math.random() * colors.length);
                currentBlocks.push({ shape: shape, color: colors[colorIndex] });
                drawBlock(i, shape, colors[colorIndex]);
            }
        }

        function drawBlock(index, shape, color) {
            const canvas = document.getElementById(`block${index + 1}`);
            const blockCtx = canvas.getContext(&#039;2d&#039;);
            blockCtx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            const offsetX = (canvas.width - (shape[0].length * blockCellSize)) / 2;
            const offsetY = (canvas.height - (shape.length * blockCellSize)) / 2;
            shape.forEach((row, y) =&gt; {
                row.forEach((cell, x) =&gt; {
                    if (cell) {
                        blockCtx.fillStyle = color;
                        blockCtx.fillRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        blockCtx.strokeStyle = &#039;#000&#039;;
                        blockCtx.strokeRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                });
            });
        }

        function rotateShape(shape) {
            const rows = shape.length;
            const cols = shape[0].length;
            const rotated = Array(cols).fill().map(() =&gt; Array(rows).fill(0));
            for (let y = 0; y &lt; rows; y++) {
                for (let x = 0; x &lt; cols; x++) {
                    rotated[x][rows - 1 - y] = shape[y][x];
                }
            }
            return rotated;
        }

        function flipShape(shape) {
            return shape.map(row =&gt; [...row].reverse());
        }

        function showBonusMessage(message) {
            bonusMessageElement.textContent = message;
            bonusMessageElement.style.display = &#039;block&#039;;
            setTimeout(() =&gt; bonusMessageElement.style.display = &#039;none&#039;, 2000);
        }

        function drawGrid() {
            ctx.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
            for (let y = 0; y &lt; gridSize; y++) {
                for (let x = 0; x &lt; gridSize; x++) {
                    ctx.strokeStyle = &#039;#000&#039;;
                    ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize);
                    if (grid[y][x]) {
                        ctx.fillStyle = grid[y][x];
                        ctx.fillRect(x * cellSize + 2, y * cellSize + 2, cellSize - 4, cellSize - 4);
                    }
                }
            }
        }

        function drawPreview(shape, x, y, valid) {
            drawGrid();
            if (shape &amp;&amp; x &gt;= 0 &amp;&amp; y &gt;= 0) {
                ctx.globalAlpha = 0.5;
                for (let sy = 0; sy &lt; shape.length; sy++) {
                    for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                        if (shape[sy][sx]) {
                            ctx.fillStyle = valid ? selectedBlock.color : &#039;#FF0000&#039;;
                            ctx.fillRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                            ctx.strokeStyle = &#039;#000&#039;;
                            ctx.strokeRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                        }
                    }
                }
                ctx.globalAlpha = 1.0;
            }
        }

        function canPlaceBlock(shape, x, y) {
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        const gridX = x + sx;
                        const gridY = y + sy;
                        if (gridX &lt; 0 || gridX &gt;= gridSize || gridY &lt; 0 || gridY &gt;= gridSize || grid[gridY][gridX]) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        function placeBlock(shape, color, x, y, blockIndex) {
            console.log(`Розміщення блоку на позиції (${x}, ${y}), індекс: ${blockIndex}, форма:`, JSON.stringify(shape));
            lastMove = {
                grid: grid.map(row =&gt; [...row]),
                score,
                block: { shape, color },
                blockIndex
            };
            undoButton.disabled = false;
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        grid[y + sy][x + sx] = color;
                    }
                }
            }
            console.log(&#039;Блок розміщено, викликаємо checkLines&#039;);
            checkLines();
            console.log(&#039;checkLines завершено, викликаємо checkGameOver&#039;);
            checkGameOver();
            drawGrid();
            console.log(&#039;Розміщення завершено, поточна черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
        }

        function checkLines() {
            let linesCleared = 0;
            for (let y = gridSize - 1; y &gt;= 0; y--) {
                if (grid[y].every(cell =&gt; cell)) {
                    grid.splice(y, 1);
                    grid.unshift(Array(gridSize).fill(null));
                    linesCleared++;
                    y++;
                }
            }
            for (let x = gridSize - 1; x &gt;= 0; x--) {
                let isFull = true;
                for (let y = 0; y &lt; gridSize; y++) {
                    if (!grid[y][x]) {
                        isFull = false;
                        break;
                    }
                }
                if (isFull) {
                    for (let y = 0; y &lt; gridSize; y++) {
                        grid[y].splice(x, 1);
                        grid[y].push(null);
                    }
                    linesCleared++;
                    x++;
                }
            }
            if (linesCleared &gt; 0) {
                let lineBonus = linesCleared === 1 ? 100 : 100 + (linesCleared - 1) * 50;
                score += lineBonus;
                if (linesCleared &gt; 1) {
                    showBonusMessage(`Бонус за ${linesCleared} лінії: +${lineBonus} очок`);
                    console.log(`Бонус за очищення ${linesCleared} ліній: +${lineBonus} очок`);
                }
                const isGridEmpty = grid.every(row =&gt; row.every(cell =&gt; !cell));
                if (isGridEmpty &amp;&amp; score &gt; 0) {
                    const clearBonus = Math.floor(score * 0.25);
                    score += clearBonus;
                    showBonusMessage(`Бонус за повне очищення поля: +${clearBonus} очок`);
                    console.log(`Бонус за повне очищення поля: +${clearBonus} очок`);
                }
                scoreElement.textContent = `Очки: ${score}`;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    highScoreElement.textContent = `Рекорд: ${highScore}`;
                    console.log(&#039;Новий рекорд:&#039;, highScore);
                }
            }
            console.log(&#039;Очищено ліній:&#039;, linesCleared, &#039;Очки:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function checkGameOver() {
            console.log(&#039;Перевірка стану гри. Кількість блоків:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
            if (currentBlocks.length === 0) {
                console.log(&#039;Черга порожня, генеруємо нові блоки&#039;);
                setTimeout(() =&gt; {
                    generateBlocks();
                    console.log(&#039;Нові блоки згенеровано, нова черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                }, 0);
                return;
            }
            let canPlaceAny = false;
            for (let block of currentBlocks) {
                for (let y = 0; y &lt; gridSize; y++) {
                    for (let x = 0; x &lt; gridSize; x++) {
                        if (canPlaceBlock(block.shape, x, y)) {
                            canPlaceAny = true;
                            break;
                        }
                    }
                    if (canPlaceAny) break;
                }
                if (canPlaceAny) break;
            }
            console.log(&#039;Чи можна розмістити блок:&#039;, canPlaceAny);
            if (!canPlaceAny) {
                gameActive = false;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    console.log(&#039;Новий рекорд на кінці гри:&#039;, highScore);
                }
                finalScoreElement.textContent = `Ваш рахунок: ${score}\nРекорд: ${highScore}`;
                gameOverElement.style.display = &#039;block&#039;;
                console.log(&#039;Гра закінчена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
            }
        }

        function restartGame() {
            grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
            score = 0;
            scoreElement.textContent = `Очки: ${score}`;
            highScoreElement.textContent = `Рекорд: ${highScore}`;
            gameOverElement.style.display = &#039;none&#039;;
            gamePaused = false;
            pauseButton.textContent = &#039;Пауза&#039;;
            pauseOverlay.style.display = &#039;none&#039;;
            undoButton.disabled = true;
            lastMove = null;
            gameActive = true;
            currentBlocks = [];
            generateBlocks();
            drawGrid();
            console.log(&#039;Гра перезапущена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function undoMove() {
            if (!lastMove || !gameActive || gamePaused) return;
            grid = lastMove.grid.map(row =&gt; [...row]);
            score = lastMove.score;
            currentBlocks.splice(lastMove.blockIndex, 0, lastMove.block);
            scoreElement.textContent = `Очки: ${score}`;
            undoButton.disabled = true;
            lastMove = null;
            for (let i = 0; i &lt; 3; i++) {
                const blockCanvas = document.getElementById(`block${i + 1}`);
                blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                if (i &lt; currentBlocks.length) {
                    drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                }
            }
            drawGrid();
            console.log(&#039;Хід скасовано. Поточна черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
        }

        function togglePause() {
            if (!gameActive) return;
            gamePaused = !gamePaused;
            pauseButton.textContent = gamePaused ? &#039;Відновити&#039; : &#039;Пауза&#039;;
            pauseOverlay.style.display = gamePaused ? &#039;block&#039; : &#039;none&#039;;
            console.log(&#039;Гра на паузі:&#039;, gamePaused);
        }

        pauseButton.addEventListener(&#039;click&#039;, togglePause);
        undoButton.addEventListener(&#039;click&#039;, undoMove);

        const blockCanvases = document.querySelectorAll(&#039;.blockCanvas&#039;);
        blockCanvases.forEach(canvas =&gt; {
            canvas.addEventListener(&#039;dragstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                selectedBlock = currentBlocks[index];
                canvas.classList.add(&#039;dragging&#039;);
                e.dataTransfer.setData(&#039;text/plain&#039;, index);
                console.log(&#039;Початок перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
            });

            canvas.addEventListener(&#039;dragend&#039;, (e) =&gt; {
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Кінець перетягування&#039;);
            });

            canvas.addEventListener(&#039;contextmenu&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                currentBlocks[index].shape = rotateShape(currentBlocks[index].shape);
                drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                console.log(&#039;Блок повернуто:&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
            });

            canvas.addEventListener(&#039;mousedown&#039;, (e) =&gt; {
                if (e.button === 1) {
                    e.preventDefault();
                    if (!gameActive || gamePaused) return;
                    const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (середня кнопка):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });

            canvas.addEventListener(&#039;dblclick&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (подвійне клацання):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });

            canvas.addEventListener(&#039;touchstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    selectedBlock = currentBlocks[index];
                    canvas.classList.add(&#039;dragging&#039;);
                    console.log(&#039;Початок сенсорного перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
                } else {
                    console.error(&#039;Помилка: невалідний індекс блоку на touchstart&#039;, index);
                }
            });

            canvas.addEventListener(&#039;touchmove&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.touches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                const valid = canPlaceBlock(selectedBlock.shape, x, y);
                drawPreview(selectedBlock.shape, x, y, valid);
            });

            canvas.addEventListener(&#039;touchend&#039;, (e) =&gt; {
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.changedTouches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                console.log(`Сенсорне розміщення: координати (${x}, ${y}), індекс: ${index}, блок:`, JSON.stringify(selectedBlock));
                if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                    if (canPlaceBlock(selectedBlock.shape, x, y)) {
                        placeBlock(selectedBlock.shape, selectedBlock.color, x, y, index);
                        currentBlocks.splice(index, 1);
                        console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                        for (let i = 0; i &lt; 3; i++) {
                            const blockCanvas = document.getElementById(`block${i + 1}`);
                            blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                            if (i &lt; currentBlocks.length) {
                                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                            }
                        }
                        checkGameOver();
                        selectedBlock = null;
                    } else {
                        console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                    }
                } else {
                    console.error(&#039;Помилка: невалідний індекс блоку на touchend&#039;, index);
                }
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Сенсорне розміщення завершено&#039;);
            });
        });

        gameCanvas.addEventListener(&#039;dragover&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const valid = canPlaceBlock(selectedBlock.shape, x, y);
            drawPreview(selectedBlock.shape, x, y, valid);
        });

        gameCanvas.addEventListener(&#039;drop&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const index = parseInt(e.dataTransfer.getData(&#039;text/plain&#039;));
            console.log(`Розміщення через drag: координати (${x}, ${y}), індекс: ${index}, блок:`, JSON.stringify(selectedBlock));
            if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                if (canPlaceBlock(selectedBlock.shape, x, y)) {
                    placeBlock(selectedBlock.shape, selectedBlock.color, x, y, index);
                    currentBlocks.splice(index, 1);
                    console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                    for (let i = 0; i &lt; 3; i++) {
                        const blockCanvas = document.getElementById(`block${i + 1}`);
                        blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                        if (i &lt; currentBlocks.length) {
                            drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                        }
                    }
                    checkGameOver();
                    selectedBlock = null;
                } else {
                    console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                }
            } else {
                console.error(&#039;Помилка: невалідний індекс блоку на drop&#039;, index);
            }
        });

        generateBlocks();
        drawGrid();
        console.log(&#039;Гра ініціалізована — Мозаїка Майстрів Версія 1.9&#039;);
    &lt;/script&gt;</description>
            </item>
                    <item>
                <title>мм3</title>
                <link>http://margo.mozello.shop/gry/params/post/5140019/mm3</link>
                <pubDate>Tue, 30 Sep 2025 14:12:00 +0000</pubDate>
                <description>оооооооооооооооооооооооооооо&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;3&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;


    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Мозаїка Майстрів — Версія 1.9 (Виправлена)&lt;/title&gt;
    &lt;style&gt;
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
            padding: 10px;
            background-color: #f0f0f0;
            font-family: Arial, sans-serif;
            overflow: auto;
        }
        #gameCanvas {
            border: 2px solid #333;
            background-color: #e3f1c6;
            max-width: 100%;
            height: auto;
            margin-top: 20px;
        }
        #nextBlocks {
            display: flex;
            justify-content: center;
            margin-top: 10px;
            flex-wrap: wrap;
            width: 100%;
            max-width: 260px;
            gap: 1px;
        }
        .blockCanvas {
            border: 1px solid #ccc;
            cursor: grab;
            width: 80px;
            height: 80px;
            margin: 2px;
        }
        .blockCanvas.dragging {
            opacity: 0.5;
            cursor: grabbing;
        }
        #score, #highScore {
            font-size: 20px;
            margin-top: 10px;
        }
        #bonusMessage {
            display: none;
            position: fixed;
            top: 20%;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(0, 128, 0, 0.8);
            color: white;
            padding: 10px 20px;
            border-radius: 5px;
            z-index: 1000;
            font-size: 18px;
        }
        #gameOver, #pauseOverlay {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 15px;
            border-radius: 10px;
            text-align: center;
            z-index: 1000;
        }
        button {
            margin-top: 10px;
            padding: 8px 16px;
            font-size: 14px;
            cursor: pointer;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
        }
        #rotateButtons {
            margin-top: 10px;
            display: flex;
            gap: 5px;
        }
        h2 {
            margin: 10px 0;
        }
        p {
            margin: 5px 0;
        }
        .accordion {
            width: 100%;
            max-width: 500px;
            margin-top: 20px;
        }
        .accordion-item {
            border: 1px solid #333;
            margin-bottom: 5px;
            border-radius: 5px;
        }
        .accordion-header {
            background-color: #ddd;
            padding: 10px;
            cursor: pointer;
            font-size: 18px;
            font-weight: bold;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .accordion-header::after {
            content: &#039;▼&#039;;
            font-size: 14px;
        }
        .accordion-header.active::after {
            content: &#039;▲&#039;;
        }
        .accordion-content {
            display: none;
            padding: 10px;
            background-color: #fff;
        }
        .accordion-content.active {
            display: block;
        }
        .accordion-content table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 15px;
        }
        .accordion-content th, .accordion-content td {
            border: 1px solid #333;
            padding: 8px;
            text-align: center;
        }
        .accordion-content th {
            background-color: #ddd;
        }
        .accordion-content pre {
            margin: 0;
            font-size: 12px;
        }
        .accordion-content canvas {
            border: 1px solid #ccc;
        }
    &lt;/style&gt;


    &lt;h2&gt;Мозаїка Майстрів — Версія 1.9 (Виправлена)&lt;/h2&gt;
    &lt;p&gt;Права кнопка миші — поворот блоку на 90°, Жест двома пальцями — поворот на кут, Кнопка &quot;Скасувати&quot; — скасування ходу&lt;/p&gt;
    &lt;canvas id=&quot;gameCanvas&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&lt;/canvas&gt;
    &lt;button id=&quot;pauseButton&quot; fdprocessedid=&quot;imgj4r&quot;&gt;Пауза&lt;/button&gt;
    &lt;button id=&quot;undoButton&quot; disabled=&quot;&quot;&gt;Скасувати&lt;/button&gt;
    &lt;div id=&quot;nextBlocks&quot;&gt;
        &lt;canvas id=&quot;block1&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
        &lt;canvas id=&quot;block2&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
        &lt;canvas id=&quot;block3&quot; class=&quot;blockCanvas&quot; width=&quot;80&quot; height=&quot;80&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
    &lt;/div&gt;
    &lt;div id=&quot;score&quot;&gt;Очки: 0&lt;/div&gt;
    &lt;div id=&quot;highScore&quot;&gt;Рекорд: 0&lt;/div&gt;
    &lt;div id=&quot;bonusMessage&quot;&gt;&lt;/div&gt;
    &lt;div id=&quot;gameOver&quot;&gt;
        &lt;h2&gt;Гра закінчена!&lt;/h2&gt;
        &lt;p id=&quot;finalScore&quot;&gt;&lt;/p&gt;
        &lt;button onclick=&quot;restartGame()&quot;&gt;Грати знову&lt;/button&gt;
    &lt;/div&gt;
    &lt;div id=&quot;pauseOverlay&quot;&gt;
        &lt;h2&gt;Гра на паузі&lt;/h2&gt;
        &lt;button onclick=&quot;togglePause()&quot;&gt;Відновити&lt;/button&gt;
    &lt;/div&gt;
    &lt;div id=&quot;rotateButtons&quot;&gt;
        &lt;button onclick=&quot;rotateSelectedBlock(90)&quot;&gt;90°&lt;/button&gt;
        &lt;button onclick=&quot;rotateSelectedBlock(180)&quot;&gt;180°&lt;/button&gt;
        &lt;button onclick=&quot;rotateSelectedBlock(270)&quot;&gt;270°&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion&quot;&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Таблиця блоків&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;table&gt;
                    &lt;thead&gt;
                        &lt;tr&gt;
                            &lt;th&gt;Назва&lt;/th&gt;
                            &lt;th&gt;Зображення&lt;/th&gt;
                            &lt;th&gt;Структура&lt;/th&gt;
                            &lt;th&gt;Використання&lt;/th&gt;
                        &lt;/tr&gt;
                    &lt;/thead&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Одинарний&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSingle&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення окремих клітинок&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;L-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeL&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для кутів або вузьких просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;T-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeT&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1],&lt;br&gt;[0, 1, 0]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для горизонтальних ліній з виступом&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (4)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI4&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Квадрат&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeSquare&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1],&lt;br&gt;[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для компактних квадратних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Z-форма&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeZ&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 0],&lt;br&gt;[0, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для зміщених &quot;змійок&quot;&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (5)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI5&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (3)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для середніх рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;I-форма (2)&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeI2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для коротких рядків/стовпців&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 2x2&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0],&lt;br&gt;[0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для заповнення діагональних просторів&lt;/td&gt;
                        &lt;/tr&gt;
                        &lt;tr&gt;
                            &lt;td&gt;Діагональ 3x3&lt;/td&gt;
                            &lt;td&gt;&lt;canvas id=&quot;shapeDiagonal3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;&lt;/td&gt;
                            &lt;td&gt;&lt;pre&gt;[[1, 0, 0],&lt;br&gt;[0, 1, 0],&lt;br&gt;[0, 0, 1]]&lt;/pre&gt;&lt;/td&gt;
                            &lt;td&gt;Для довгих діагональних ліній&lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                &lt;/table&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;accordion-item&quot;&gt;
            &lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;Інструкція&lt;/div&gt;
            &lt;div class=&quot;accordion-content&quot;&gt;
                &lt;h3&gt;Мета гри&lt;/h3&gt;
                &lt;p&gt;&quot;Мозаїка Майстрів&quot; — це головоломка, де гравець розміщує блоки на сітці 10x10, щоб очищати цілі рядки або стовпці. Мета — набрати якомога більше очок і встановити рекорд. Гра закінчується, коли жоден блок не можна розмістити.&lt;/p&gt;
                
                &lt;h3&gt;Правила гри&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Ігрове поле&lt;/b&gt;: Сітка 10x10, де клітинки можуть бути порожніми або заповненими.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Черга блоків&lt;/b&gt;: До трьох блоків відображаються знизу для розміщення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Розміщення&lt;/b&gt;: Перетягуйте блоки на сітку. Розміщення можливе лише у вільних місцях.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Очищення ліній&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;Повний рядок або стовпець очищається.&lt;/li&gt;
                            &lt;li&gt;1 лінія: 100 очок.&lt;/li&gt;
                            &lt;li&gt;2+ ліній: 100 + 50 за кожну додаткову (наприклад, 2 лінії = 150 очок).&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Бонус за очищення поля&lt;/b&gt;: 25% від суми очок, якщо поле порожнє.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Рекорд&lt;/b&gt;: Зберігається у браузері, відображається під час гри та після завершення.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Кінець гри&lt;/b&gt;: Гра закінчується, якщо блоки неможливо розмістити.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Дії гравця&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;b&gt;Перетягування&lt;/b&gt;:
                        &lt;ul&gt;
                            &lt;li&gt;ПК: Лівою кнопкою миші.&lt;/li&gt;
                            &lt;li&gt;Сенсорні пристрої: Торкніться та перетягніть.&lt;/li&gt;
                        &lt;/ul&gt;
                    &lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Поворот&lt;/b&gt;: Кнопки 90°/180°/270° або жест двома пальцями.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Скасування ходу&lt;/b&gt;: Кнопка &quot;Скасувати&quot; для останнього ходу.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Пауза&lt;/b&gt;: Кнопка &quot;Пауза&quot;/&quot;Відновити&quot;.&lt;/li&gt;
                    &lt;li&gt;&lt;b&gt;Перезапуск&lt;/b&gt;: Кнопка &quot;Грати знову&quot; на екрані &quot;Гра закінчена&quot;.&lt;/li&gt;
                &lt;/ul&gt;

                &lt;h3&gt;Поради&lt;/h3&gt;
                &lt;ul&gt;
                    &lt;li&gt;Плануйте ходи, щоб створювати повні лінії.&lt;/li&gt;
                    &lt;li&gt;Використовуйте одинарний блок для прогалин.&lt;/li&gt;
                    &lt;li&gt;Скасовуйте невдалі ходи.&lt;/li&gt;
                    &lt;li&gt;Намагайтеся очищати кілька ліній для бонусів.&lt;/li&gt;
                    &lt;li&gt;Експериментуйте з діагональними блоками для унікальних комбінацій.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;script&gt;
        // Акордеон-меню
        function toggleAccordion(header) {
            const content = header.nextElementSibling;
            const isActive = content.classList.contains(&#039;active&#039;);
            document.querySelectorAll(&#039;.accordion-content&#039;).forEach(item =&gt; {
                item.classList.remove(&#039;active&#039;);
                item.previousElementSibling.classList.remove(&#039;active&#039;);
            });
            if (!isActive) {
                content.classList.add(&#039;active&#039;);
                header.classList.add(&#039;active&#039;);
            }
        }

        // Ігрова логіка
        const gameCanvas = document.getElementById(&#039;gameCanvas&#039;);
        const ctx = gameCanvas.getContext(&#039;2d&#039;);
        const gridSize = 10;
        const cellSize = gameCanvas.width / gridSize; // 30px
        const scoreElement = document.getElementById(&#039;score&#039;);
        const highScoreElement = document.getElementById(&#039;highScore&#039;);
        const bonusMessageElement = document.getElementById(&#039;bonusMessage&#039;);
        const gameOverElement = document.getElementById(&#039;gameOver&#039;);
        const finalScoreElement = document.getElementById(&#039;finalScore&#039;);
        const pauseButton = document.getElementById(&#039;pauseButton&#039;);
        const undoButton = document.getElementById(&#039;undoButton&#039;);
        const pauseOverlay = document.getElementById(&#039;pauseOverlay&#039;);

        let grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
        let score = 0;
        let highScore = parseInt(localStorage.getItem(&#039;blockLegendHighScore&#039;)) || 0;
        let currentBlocks = [];
        let selectedBlock = null;
        let selectedBlockIndex = -1;
        let gameActive = true;
        let gamePaused = false;
        let lastMove = null;

        highScoreElement.textContent = `Рекорд: ${highScore}`;
        console.log(&#039;Завантажено рекорд:&#039;, highScore);

        const blockShapes = [
            [[1]], // Одинарний
            [[1, 1], [1, 0]], // L-форма
            [[1, 1, 1], [0, 1, 0]], // T-форма
            [[1, 1, 1, 1]], // I-форма (4)
            [[1, 1], [1, 1]], // Квадрат
            [[1, 1, 0], [0, 1, 1]], // Z-форма
            [[1, 1, 1, 1, 1]], // I-форма (5)
            [[1, 1, 1]], // I-форма (3)
            [[1, 1]], // I-форма (2)
            [[1, 0], [0, 1]], // Діагональ 2x2
            [[1, 0, 0], [0, 1, 0], [0, 0, 1]] // Діагональ 3x3
        ];

        const colors = [&#039;#FF0000&#039;, &#039;#00FF00&#039;, &#039;#0000FF&#039;, &#039;#FFFF00&#039;, &#039;#FF00FF&#039;, &#039;#FFA500&#039;, &#039;#800080&#039;, &#039;#00FFFF&#039;, &#039;#FF4500&#039;, &#039;#2E8B57&#039;, &#039;#DAA520&#039;, &#039;#8A2BE2&#039;];

        // Малювання блоків у таблиці
        function drawTableBlock(canvasId, shape, color) {
            const canvas = document.getElementById(canvasId);
            const ctx = canvas.getContext(&#039;2d&#039;);
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            shape.forEach((row, y) =&gt; {
                row.forEach((cell, x) =&gt; {
                    if (cell) {
                        ctx.fillStyle = color;
                        ctx.fillRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        ctx.strokeStyle = &#039;#000&#039;;
                        ctx.strokeRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                });
            });
        }

        // Ініціалізація малюнків у таблиці
        drawTableBlock(&#039;shapeSingle&#039;, blockShapes[0], colors[0]);
        drawTableBlock(&#039;shapeL&#039;, blockShapes[1], colors[1]);
        drawTableBlock(&#039;shapeT&#039;, blockShapes[2], colors[2]);
        drawTableBlock(&#039;shapeI4&#039;, blockShapes[3], colors[3]);
        drawTableBlock(&#039;shapeSquare&#039;, blockShapes[4], colors[4]);
        drawTableBlock(&#039;shapeZ&#039;, blockShapes[5], colors[0]);
        drawTableBlock(&#039;shapeI5&#039;, blockShapes[6], colors[5]);
        drawTableBlock(&#039;shapeI3&#039;, blockShapes[7], colors[6]);
        drawTableBlock(&#039;shapeI2&#039;, blockShapes[8], colors[1]);
        drawTableBlock(&#039;shapeDiagonal2&#039;, blockShapes[9], colors[10]);
        drawTableBlock(&#039;shapeDiagonal3&#039;, blockShapes[10], colors[11]);

        function showBonusMessage(message) {
            bonusMessageElement.textContent = message;
            bonusMessageElement.style.display = &#039;block&#039;;
            setTimeout(() =&gt; bonusMessageElement.style.display = &#039;none&#039;, 2000);
        }

        function drawGrid() {
            ctx.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
            for (let y = 0; y &lt; gridSize; y++) {
                for (let x = 0; x &lt; gridSize; x++) {
                    ctx.strokeStyle = &#039;#000&#039;;
                    ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize);
                    if (grid[y][x]) {
                        ctx.fillStyle = grid[y][x];
                        ctx.fillRect(x * cellSize + 2, y * cellSize + 2, cellSize - 4, cellSize - 4);
                    }
                }
            }
        }

        function drawPreview(shape, x, y, valid) {
            drawGrid();
            if (shape &amp;&amp; x &gt;= 0 &amp;&amp; y &gt;= 0) {
                ctx.globalAlpha = 0.5;
                for (let sy = 0; sy &lt; shape.length; sy++) {
                    for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                        if (shape[sy][sx]) {
                            ctx.fillStyle = valid ? selectedBlock.color : &#039;#FF0000&#039;;
                            ctx.fillRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                            ctx.strokeStyle = &#039;#000&#039;;
                            ctx.strokeRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                        }
                    }
                }
                ctx.globalAlpha = 1.0;
            }
        }

        function canPlaceBlock(shape, x, y) {
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        const gridX = x + sx;
                        const gridY = y + sy;
                        if (gridX &lt; 0 || gridX &gt;= gridSize || gridY &lt; 0 || gridY &gt;= gridSize || grid[gridY][gridX]) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        function placeBlock(shape, color, x, y, blockIndex) {
            console.log(`Розміщення блоку на позиції (${x}, ${y}), індекс: ${blockIndex}, форма:`, JSON.stringify(shape));
            lastMove = {
                grid: grid.map(row =&gt; [...row]),
                score,
                block: { shape, color },
                blockIndex
            };
            undoButton.disabled = false;
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        grid[y + sy][x + sx] = color;
                    }
                }
            }
            console.log(&#039;Блок розміщено, викликаємо checkLines&#039;);
            checkLines();
            console.log(&#039;checkLines завершено, викликаємо checkGameOver&#039;);
            checkGameOver();
            drawGrid();
            console.log(&#039;Розміщення завершено, поточна черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
        }

        function checkLines() {
            let linesCleared = 0;
            for (let y = gridSize - 1; y &gt;= 0; y--) {
                if (grid[y].every(cell =&gt; cell)) {
                    grid.splice(y, 1);
                    grid.unshift(Array(gridSize).fill(null));
                    linesCleared++;
                    y++;
                }
            }
            for (let x = gridSize - 1; x &gt;= 0; x--) {
                let isFull = true;
                for (let y = 0; y &lt; gridSize; y++) {
                    if (!grid[y][x]) {
                        isFull = false;
                        break;
                    }
                }
                if (isFull) {
                    for (let y = 0; y &lt; gridSize; y++) {
                        grid[y].splice(x, 1);
                        grid[y].push(null);
                    }
                    linesCleared++;
                    x++;
                }
            }
            if (linesCleared &gt; 0) {
                let lineBonus = linesCleared === 1 ? 100 : 100 + (linesCleared - 1) * 50;
                score += lineBonus;
                if (linesCleared &gt; 1) {
                    showBonusMessage(`Бонус за ${linesCleared} лінії: +${lineBonus} очок`);
                    console.log(`Бонус за очищення ${linesCleared} ліній: +${lineBonus} очок`);
                }
                const isGridEmpty = grid.every(row =&gt; row.every(cell =&gt; !cell));
                if (isGridEmpty &amp;&amp; score &gt; 0) {
                    const clearBonus = Math.floor(score * 0.25);
                    score += clearBonus;
                    showBonusMessage(`Бонус за повне очищення поля: +${clearBonus} очок`);
                    console.log(`Бонус за повне очищення поля: +${clearBonus} очок`);
                }
                scoreElement.textContent = `Очки: ${score}`;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    highScoreElement.textContent = `Рекорд: ${highScore}`;
                    console.log(&#039;Новий рекорд:&#039;, highScore);
                }
            }
            console.log(&#039;Очищено ліній:&#039;, linesCleared, &#039;Очки:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function checkGameOver() {
            console.log(&#039;Перевірка стану гри. Кількість блоків:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
            if (currentBlocks.length === 0) {
                console.log(&#039;Черга порожня, генеруємо нові блоки&#039;);
                setTimeout(() =&gt; {
                    generateBlocks();
                    console.log(&#039;Нові блоки згенеровано, нова черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                }, 0);
                return;
            }
            let canPlaceAny = false;
            for (let block of currentBlocks) {
                for (let y = 0; y &lt; gridSize; y++) {
                    for (let x = 0; x &lt; gridSize; x++) {
                        if (canPlaceBlock(block.shape, x, y)) {
                            canPlaceAny = true;
                            break;
                        }
                    }
                    if (canPlaceAny) break;
                }
                if (canPlaceAny) break;
            }
            console.log(&#039;Чи можна розмістити блок:&#039;, canPlaceAny);
            if (!canPlaceAny) {
                gameActive = false;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    console.log(&#039;Новий рекорд на кінці гри:&#039;, highScore);
                }
                finalScoreElement.textContent = `Ваш рахунок: ${score}\nРекорд: ${highScore}`;
                gameOverElement.style.display = &#039;block&#039;;
                console.log(&#039;Гра закінчена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
            }
        }

        function restartGame() {
            grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
            score = 0;
            scoreElement.textContent = `Очки: ${score}`;
            highScoreElement.textContent = `Рекорд: ${highScore}`;
            gameOverElement.style.display = &#039;none&#039;;
            gamePaused = false;
            pauseButton.textContent = &#039;Пауза&#039;;
            pauseOverlay.style.display = &#039;none&#039;;
            undoButton.disabled = true;
            lastMove = null;
            gameActive = true;
            currentBlocks = [];
            generateBlocks();
            drawGrid();
            console.log(&#039;Гра перезапущена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function togglePause() {
            if (!gameActive) return;
            gamePaused = !gamePaused;
            pauseButton.textContent = gamePaused ? &#039;Відновити&#039; : &#039;Пауза&#039;;
            pauseOverlay.style.display = gamePaused ? &#039;block&#039; : &#039;none&#039;;
            console.log(&#039;Гра на паузі:&#039;, gamePaused);
        }

        pauseButton.addEventListener(&#039;click&#039;, togglePause);
        undoButton.addEventListener(&#039;click&#039;, undoMove);

        const blockCanvases = document.querySelectorAll(&#039;.blockCanvas&#039;);
        let touchStart = { x1: 0, y1: 0, x2: 0, y2: 0, time: 0 };

        blockCanvases.forEach(canvas =&gt; {
            canvas.addEventListener(&#039;dragstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                selectedBlock = currentBlocks[index];
                selectedBlockIndex = index;
                canvas.classList.add(&#039;dragging&#039;);
                e.dataTransfer.setData(&#039;text/plain&#039;, index);
                console.log(&#039;Початок перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
            });

            canvas.addEventListener(&#039;dragend&#039;, (e) =&gt; {
                canvas.classList.remove(&#039;dragging&#039;);
                selectedBlock = null;
                selectedBlockIndex = -1;
                drawGrid();
                console.log(&#039;Кінець перетягування&#039;);
            });

            canvas.addEventListener(&#039;contextmenu&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                rotateSelectedBlock(90, index);
                drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                console.log(&#039;Блок повернуто на 90°:&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
            });

            canvas.addEventListener(&#039;touchstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused || e.touches.length &lt; 1) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                selectedBlock = currentBlocks[index];
                selectedBlockIndex = index;
                canvas.classList.add(&#039;dragging&#039;);
                if (e.touches.length === 1) {
                    touchStart = { x1: e.touches[0].clientX, y1: e.touches[0].clientY, time: Date.now() };
                } else if (e.touches.length === 2) {
                    touchStart = { x1: e.touches[0].clientX, y1: e.touches[0].clientY, x2: e.touches[1].clientX, y2: e.touches[1].clientY, time: Date.now() };
                }
                console.log(&#039;Початок сенсорного перетягування/ротації блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
            });

            canvas.addEventListener(&#039;touchmove&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused || e.touches.length !== 2 || selectedBlockIndex === -1) return;
                const touch1 = e.touches[0];
                const touch2 = e.touches[1];
                const dx = touch2.clientX - touch1.clientX;
                const dy = touch2.clientY - touch1.clientY;
                const startDx = touchStart.x2 - touchStart.x1;
                const startDy = touchStart.y2 - touchStart.y1;
                let angle = Math.atan2(dy, dx) - Math.atan2(startDy, startDx);
                angle = Math.round(degrees(angle) / 90) * 90; // Округлення до найближчих 90°
                rotateSelectedBlock(angle, selectedBlockIndex);
                drawBlock(selectedBlockIndex, currentBlocks[selectedBlockIndex].shape, currentBlocks[selectedBlockIndex].color);
                touchStart = { x1: touch1.clientX, y1: touch1.clientY, x2: touch2.clientX, y2: touch2.clientY, time: Date.now() };
            });

            canvas.addEventListener(&#039;touchend&#039;, (e) =&gt; {
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.changedTouches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                console.log(`Сенсорне розміщення: координати (${x}, ${y}), індекс: ${selectedBlockIndex}, блок:`, JSON.stringify(selectedBlock));
                if (selectedBlockIndex &gt;= 0 &amp;&amp; selectedBlockIndex &lt; currentBlocks.length) {
                    if (canPlaceBlock(selectedBlock.shape, x, y)) {
                        placeBlock(selectedBlock.shape, selectedBlock.color, x, y, selectedBlockIndex);
                        currentBlocks.splice(selectedBlockIndex, 1);
                        console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length);
                        for (let i = 0; i &lt; 3; i++) {
                            const blockCanvas = document.getElementById(`block${i + 1}`);
                            blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                            if (i &lt; currentBlocks.length) {
                                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                            }
                        }
                        checkGameOver();
                        selectedBlock = null;
                        selectedBlockIndex = -1;
                    } else {
                        console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                    }
                }
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Сенсорне розміщення завершено&#039;);
                touchStart = null;
            });

            canvas.addEventListener(&#039;mousedown&#039;, (e) =&gt; {
                if (e.button === 1) {
                    e.preventDefault();
                    if (!gameActive || gamePaused) return;
                    const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (середня кнопка):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });
        });

        gameCanvas.addEventListener(&#039;dragover&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const valid = canPlaceBlock(selectedBlock.shape, x, y);
            drawPreview(selectedBlock.shape, x, y, valid);
        });

        gameCanvas.addEventListener(&#039;drop&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const index = parseInt(e.dataTransfer.getData(&#039;text/plain&#039;));
            console.log(`Розміщення через drag: координати (${x}, ${y}), індекс: ${index}, блок:`, JSON.stringify(selectedBlock));
            if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                if (canPlaceBlock(selectedBlock.shape, x, y)) {
                    placeBlock(selectedBlock.shape, selectedBlock.color, x, y, index);
                    currentBlocks.splice(index, 1);
                    console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length);
                    for (let i = 0; i &lt; 3; i++) {
                        const blockCanvas = document.getElementById(`block${i + 1}`);
                        blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                        if (i &lt; currentBlocks.length) {
                            drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                        }
                    }
                    checkGameOver();
                    selectedBlock = null;
                    selectedBlockIndex = -1;
                } else {
                    console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                }
            } else {
                console.error(&#039;Помилка: невалідний індекс блоку на drop&#039;, index);
            }
        });

        function generateBlocks() {
            currentBlocks = [];
            for (let i = 0; i &lt; 3; i++) {
                const shapeIndex = Math.floor(Math.random() * blockShapes.length);
                const colorIndex = Math.floor(Math.random() * colors.length);
                currentBlocks.push({ shape: blockShapes[shapeIndex], color: colors[colorIndex] });
                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
            }
        }

        function drawBlock(index, shape, color) {
            const canvas = document.getElementById(`block${index + 1}`);
            const blockCtx = canvas.getContext(&#039;2d&#039;);
            blockCtx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            const offsetX = (canvas.width - maxSize * blockCellSize) / 2;
            const offsetY = (canvas.height - maxSize * blockCellSize) / 2;
            for (let y = 0; y &lt; shape.length; y++) {
                for (let x = 0; x &lt; shape[y].length; x++) {
                    if (shape[y][x]) {
                        blockCtx.fillStyle = color;
                        blockCtx.fillRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        blockCtx.strokeStyle = &#039;#000&#039;;
                        blockCtx.strokeRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                }
            }
        }

        function rotateSelectedBlock(angle, index) {
            if (index === undefined || index &lt; 0 || index &gt;= currentBlocks.length) {
                console.error(&#039;Невірний індекс блоку для ротації:&#039;, index);
                return;
            }
            let shape = currentBlocks[index].shape;
            let newShape = Array(shape[0].length).fill().map(() =&gt; Array(shape.length).fill(0));
            for (let y = 0; y &lt; shape.length; y++) {
                for (let x = 0; x &lt; shape[y].length; x++) {
                    let newX, newY;
                    if (angle === 90) {
                        newX = shape.length - 1 - y;
                        newY = x;
                    } else if (angle === 180) {
                        newX = shape[y].length - 1 - x;
                        newY = shape.length - 1 - y;
                    } else if (angle === 270) {
                        newX = y;
                        newY = shape[0].length - 1 - x;
                    } else {
                        return; // Нічого не робимо для інших кутів
                    }
                    newShape[newY][newX] = shape[y][x];
                }
            }
            currentBlocks[index].shape = newShape;
            drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
            console.log(`Блок повернуто на ${angle}°:`, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
        }

        function flipShape(shape) {
            return shape[0].map((_, col) =&gt; shape.map(row =&gt; row[col]).reverse());
        }

        function undoMove() {
            if (lastMove) {
                grid = lastMove.grid;
                score = lastMove.score;
                currentBlocks[lastMove.blockIndex] = lastMove.block;
                scoreElement.textContent = `Очки: ${score}`;
                drawGrid();
                drawBlock(lastMove.blockIndex, currentBlocks[lastMove.blockIndex].shape, currentBlocks[lastMove.blockIndex].color);
                lastMove = null;
                undoButton.disabled = true;
                console.log(&#039;Хід скасовано&#039;);
            }
        }

        generateBlocks();
        drawGrid();
        console.log(&#039;Гра ініціалізована — Мозаїка Майстрів Версія 1.9&#039;);
    &lt;/script&gt;</description>
            </item>
            </channel>
</rss>