<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
    <channel>
        <title>Маргарита - Блог3</title>
        <link>http://margo.mozello.shop/blog3/</link>
        <description>Маргарита - Блог3</description>
                    <item>
                <title>Гра 2048 6 6 темна тема</title>
                <link>http://margo.mozello.shop/blog3/params/post/5198958/4</link>
                <pubDate>Fri, 23 Jan 2026 16:40:00 +0000</pubDate>
                <description>Початок 23 лютого 2026&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;3&amp;nbsp;
&lt;span style=&quot;text-align: start; font-weight: 400; font-style: normal&quot;&gt;Початок 23 лютого 2026&lt;/span&gt;

&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-align: start; font-weight: 400; font-style: normal&quot;&gt;3 2026&amp;nbsp; Початок 1 березня кінець 9 березня&lt;br&gt;4 почоток 10 березня&amp;nbsp; кінець 12 березня 2 900 000&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-align: start; font-weight: 400; font-style: normal&quot;&gt;початок&amp;nbsp; &amp;nbsp;26 03 2026&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-align: start; font-weight: 400; font-style: normal&quot;&gt;початок 31 березня 2026 року&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-align: start; font-weight: 400; font-style: normal&quot;&gt;&lt;img src=&quot;https://site-2669532.mozfiles.com/files/2669532/12__03_2026____2_900_000.jpg&quot; alt=&quot;12__03_2026____2_900_000.jpg&quot;&gt;&lt;br&gt;&lt;/span&gt;&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; }
.tile[data-value=&quot;4096&quot;]    { background: #00ff00;color: #fff;  }
.tile[data-value=&quot;8192&quot;]    { background: #8B008B; color: #fff; }
.tile[data-value=&quot;262144&quot;]    { background: #4B0082; color: #fff; }
.tile[data-value=&quot;16384&quot;]   { background: #f59563; color: #fff; }
.tile[data-value=&quot;32768&quot;]   { background: #f67c5f; color: #fff; }
.tile[data-value=&quot;65536&quot;]   { background: #f65e3b; color: #fff; }
.tile[data-value=&quot;131072&quot;]  { background: #DE3163; 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>2048 6 6 ускладнена</title>
                <link>http://margo.mozello.shop/blog3/params/post/5190419/page</link>
                <pubDate>Sat, 03 Jan 2026 18:38: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;apple-mobile-web-app-capable&quot; content=&quot;yes&quot;&gt;
  &lt;meta name=&quot;apple-mobile-web-app-status-bar-style&quot; content=&quot;black-translucent&quot;&gt;
  &lt;title&gt;2048 (6x6) Ускладнена&lt;/title&gt;
  &lt;style&gt;
    body {
      font-family: -apple-system, sans-serif;
      display: flex;
      flex-direction: column;
      align-items: center;
      background: #faf8ef;
      margin: 0;
      touch-action: none; /* Prevent iOS scrolling */
      -webkit-touch-callout: none; /* Disable iOS callouts */
      -webkit-user-select: none; /* Disable text selection */
      min-height: 80vh;
    }
    #game-board {
      display: grid;
      grid-template-columns: repeat(6, 10vw);
      gap: 2vw;
      margin: 4vw auto;
      max-width: 110vw;
    }
    .tile {
      width: 11vw;
      height: 5vw;
      background: #cdc1b4;
      font-size: calc(3vw);
      color: #776e65;
      display: flex;
      justify-content: center;
      align-items: center;
      font-weight: bold;
      border-radius: 3px;
      transition: transform 0.05s ease, background 0.05s ease; /* Прискорена анімація */
    }
    .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: #f9f6f2; }
    .tile[data-value=&quot;16&quot;]   { background: #f59563; color: #f9f6f2; }
    .tile[data-value=&quot;32&quot;]   { background: #f67c5f; color: #f9f6f2; }
    .tile[data-value=&quot;64&quot;]   { background: #f65e3b; color: #f9f6f2; }
    .tile[data-value=&quot;128&quot;]  { background: #edcf72; color: #f9f6f2; }
    .tile[data-value=&quot;256&quot;]  { background: #edcc61; color: #f9f6f2; }
    .tile[data-value=&quot;512&quot;]  { background: #edc850; color: #f9f6f2; }
    .tile[data-value=&quot;1024&quot;] { background: #edc53f; color: #f9f6f2; }
    .tile[data-value=&quot;2048&quot;] { background: #edc22e; color: #f9f6f2; }
    .tile[data-value=&quot;4096&quot;],
    .tile[data-value=&quot;8192&quot;],
    .tile[data-value=&quot;16384&quot;],
    .tile[data-value=&quot;32768&quot;] {
      background: #0000e6;
      color: #ffeb3b;
    }
    .tile[data-value=&quot;65536&quot;] { background: #DE3163; color: #f9f6f2; }
    .tile[data-value=&quot;131072&quot;] { background: #DE3163; color: #f9f6f2; }
    .tile.moved {
      transform: scale(1.1);
    }
    h1 {
      font-size: 8vw;
      margin: 4vw 0;
    }
    .info {
      font-size: 4vw;
      margin: 2vw 0;
    }
    #message {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background: #ffffffdd;
      padding: 6vw;
      border-radius: 3vw;
      display: none;
      box-shadow: 0 0 10px rgba(0,0,0,0.3);
      text-align: center;
      z-index: 10;
      font-size: 5vw;
    }
    #message button {
      font-size: 4vw;
      padding: 2vw 4vw;
      margin-top: 2vw;
      border-radius: 2vw;
      min-width: 25vw;
    }
    #restart, #increase-level, #decrease-level {
      font-size: 4vw;
      padding: 2vw 4vw;
      border-radius: 2vw;
      min-width: 25vw;
      margin: 1vw;
    }
    .controls {
      display: flex;
      justify-content: center;
      margin: 2vw 0;
    }
    @media (max-width: 414px) {
      #game-board {
        grid-template-columns: repeat(6, 14vw);
        gap: 1vw;
      }
      .tile {
        width: 14vw;
        height: 14vw;
        font-size: calc(5vw);
      }
      h1 {
        font-size: 7vw;
      }
      .info {
        font-size: 3.5vw;
      }
    }
  &lt;/style&gt;


  &lt;h1&gt;2048 (6x6) Ускладнена&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;div class=&quot;info&quot; id=&quot;level&quot;&gt;Рівень: 1&lt;/div&gt;
  &lt;div class=&quot;controls&quot;&gt;
    &lt;button id=&quot;restart&quot; fdprocessedid=&quot;8y4t5&quot;&gt;Нова гра&lt;/button&gt;
    &lt;button id=&quot;increase-level&quot; fdprocessedid=&quot;kejura&quot;&gt;Підвищити рівень&lt;/button&gt;
    &lt;button id=&quot;decrease-level&quot; fdprocessedid=&quot;hmsjo&quot;&gt;Понизити рівень&lt;/button&gt;
  &lt;/div&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;script&gt;
    const GRID_SIZE = 6;
    const TOTAL_TILES = GRID_SIZE * GRID_SIZE;
    const board = document.getElementById(&#039;game-board&#039;);
    const scoreEl = document.getElementById(&#039;score&#039;);
    const bestEl = document.getElementById(&#039;best&#039;);
    const levelEl = document.getElementById(&#039;level&#039;);
    const message = document.getElementById(&#039;message&#039;);
    const messageText = document.getElementById(&#039;message-text&#039;);
    const continueBtn = document.getElementById(&#039;continue&#039;);
    const increaseLevelBtn = document.getElementById(&#039;increase-level&#039;);
    const decreaseLevelBtn = document.getElementById(&#039;decrease-level&#039;);
    let tiles, values, score, best, gameOver, allowContinue;
    let tilesToAdd = 1;
    let level = 1;

    function slide(line) {
      let newLine = line.filter(v =&gt; v !== 0);
      for (let i = 0; i &lt; newLine.length - 1; i++) {
        if (newLine[i] === newLine[i + 1]) {
          newLine[i] *= 2;
          score += newLine[i];
          newLine[i + 1] = 0;
        }
      }
      newLine = newLine.filter(v =&gt; v !== 0);
      while (newLine.length &lt; GRID_SIZE) newLine.push(0);
      return newLine;
    }

    function updateBoard() {
      for (let i = 0; i &lt; TOTAL_TILES; i++) {
        const v = values[i];
        tiles[i].dataset.value = v || &#039;&#039;;
        tiles[i].textContent = v || &#039;&#039;;
      }
    }

    function updateScore() {
      scoreEl.textContent = `Окуляри: ${score}`;
      best = Math.max(best, score);
      bestEl.textContent = `Рекорд: ${best}`;
      localStorage.setItem(&#039;game2048_best_6x6&#039;, best);

      // Оновлення рівня на основі очок (автоматично, якщо потрібно)
      if (score &gt; 1000 * level) {
        level++;
        tilesToAdd = Math.min(level, 3);
        levelEl.textContent = `Рівень: ${level}`;
      }
    }

    function addTile() {
      const empty = values.reduce((acc, v, i) =&gt; { if (!v) acc.push(i); return acc; }, []);
      if (empty.length) {
        const idx = empty[Math.floor(Math.random() * empty.length)];
        values[idx] = Math.random() &lt; 0.9 ? 2 : 4;
      }
    }

    function move(direction) {
      if (gameOver) return;
      let moved = false;
      for (let i = 0; i &lt; GRID_SIZE; i++) {
        let line = [];
        for (let j = 0; j &lt; GRID_SIZE; j++) {
          let idx = direction === &#039;left&#039;  ? i * GRID_SIZE + j :
                    direction === &#039;right&#039; ? i * GRID_SIZE + (GRID_SIZE - 1 - j) :
                    direction === &#039;up&#039;    ? j * GRID_SIZE + i :
                                            (GRID_SIZE - 1 - j) * GRID_SIZE + i;
          line.push(values[idx]);
        }

        const newLine = slide(line);

        for (let j = 0; j &lt; GRID_SIZE; j++) {
          let idx = direction === &#039;left&#039;  ? i * GRID_SIZE + j :
                    direction === &#039;right&#039; ? i * GRID_SIZE + (GRID_SIZE - 1 - j) :
                    direction === &#039;up&#039;    ? j * GRID_SIZE + i :
                                            (GRID_SIZE - 1 - j) * GRID_SIZE + i;
          if (values[idx] !== newLine[j]) {
            values[idx] = newLine[j];
            moved = true;
            tiles[idx].classList.add(&#039;moved&#039;);
            setTimeout(() =&gt; tiles[idx].classList.remove(&#039;moved&#039;), 50);
          }
        }
      }

      if (moved) {
        for (let k = 0; k &lt; tilesToAdd; k++) {
          addTile();
        }
        updateBoard();
        updateScore();
        checkWinLose();
        if (navigator.vibrate) navigator.vibrate(10);
      }
    }

    function checkWinLose() {
      if (!allowContinue &amp;&amp; values.includes(2048)) {
        showMessage(&#039;Ви виграли! 🎉&#039;);
        gameOver = true;
      } else if (!canMove()) {
        showMessage(&#039;Гру завершено!&#039;);
        gameOver = true;
      }
    }

    function showMessage(text) {
      messageText.textContent = text;
      message.style.display = &#039;block&#039;;
    }

    function restartGame() {
      values = new Array(TOTAL_TILES).fill(0);
      score = 0;
      level = 1;
      tilesToAdd = 1;
      gameOver = false;
      allowContinue = false;
      addTile(); addTile();
      updateBoard();
      updateScore();
      levelEl.textContent = `Рівень: ${level}`;
      message.style.display = &#039;none&#039;;
      saveGame();
    }

    function increaseLevel() {
      level = Math.min(level + 1, 10); // Max level 10, for example
      tilesToAdd = Math.min(level, 3);
      levelEl.textContent = `Рівень: ${level}`;
      saveGame();
    }

    function decreaseLevel() {
      level = Math.max(level - 1, 1); // Min level 1
      tilesToAdd = Math.min(level, 3);
      levelEl.textContent = `Рівень: ${level}`;
      saveGame();
    }

    function canMove() {
      if (values.includes(0)) return true;
      for (let i = 0; i &lt; GRID_SIZE; i++) {
        for (let j = 0; j &lt; GRID_SIZE - 1; j++) {
          if (values[i * GRID_SIZE + j] === values[i * GRID_SIZE + j + 1] ||
              values[j * GRID_SIZE + i] === values[(j + 1) * GRID_SIZE + i]) return true;
        }
      }
      return false;
    }

    function saveGame() {
      localStorage.setItem(&#039;game2048_values_6x6&#039;, JSON.stringify(values));
      localStorage.setItem(&#039;game2048_score_6x6&#039;, score);
      localStorage.setItem(&#039;game2048_level_6x6&#039;, level);
      localStorage.setItem(&#039;game2048_tilesToAdd_6x6&#039;, tilesToAdd);
    }

    function loadGame() {
      const savedValues = localStorage.getItem(&#039;game2048_values_6x6&#039;);
      const savedScore = localStorage.getItem(&#039;game2048_score_6x6&#039;);
      const savedLevel = localStorage.getItem(&#039;game2048_level_6x6&#039;);
      const savedTilesToAdd = localStorage.getItem(&#039;game2048_tilesToAdd_6x6&#039;);
      if (savedValues) {
        values = JSON.parse(savedValues);
        score = parseInt(savedScore) || 0;
        level = parseInt(savedLevel) || 1;
        tilesToAdd = parseInt(savedTilesToAdd) || 1;
      } else {
        values = new Array(TOTAL_TILES).fill(0);
        addTile(); addTile();
      }
      updateBoard();
      updateScore();
      levelEl.textContent = `Рівень: ${level}`;
    }

    function loadBest() {
      best = parseInt(localStorage.getItem(&#039;game2048_best_6x6&#039;)) || 0;
      bestEl.textContent = `Рекорд: ${best}`;
    }

    function init() {
      tiles = [];
      board.innerHTML = &#039;&#039;;
      for (let i = 0; i &lt; TOTAL_TILES; i++) {
        const tile = document.createElement(&#039;div&#039;);
        tile.className = &#039;tile&#039;;
        board.appendChild(tile);
        tiles.push(tile);
      }
      loadGame();
    }

    document.addEventListener(&#039;keydown&#039;, e =&gt; {
      if ([&quot;ArrowUp&quot;, &quot;ArrowDown&quot;, &quot;ArrowLeft&quot;, &quot;ArrowRight&quot;].includes(e.key)) {
        e.preventDefault();
        move({
          ArrowLeft: &#039;left&#039;,
          ArrowRight: &#039;right&#039;,
          ArrowUp: &#039;up&#039;,
          ArrowDown: &#039;down&#039;
        }[e.key]);
      }
    });

    let startX, startY;
    board.addEventListener(&#039;touchstart&#039;, e =&gt; {
      e.preventDefault();
      const t = e.touches[0];
      startX = t.clientX;
      startY = t.clientY;
    });

    board.addEventListener(&#039;touchend&#039;, e =&gt; {
      e.preventDefault();
      const t = e.changedTouches[0];
      const dx = t.clientX - startX;
      const dy = t.clientY - startY;
      if (Math.abs(dx) &gt; Math.abs(dy)) {
        if (dx &gt; 20) move(&#039;right&#039;);
        else if (dx &lt; -20) move(&#039;left&#039;);
      } else {
        if (dy &gt; 20) move(&#039;down&#039;);
        else if (dy &lt; -20) move(&#039;up&#039;);
      }
    });

    document.getElementById(&#039;restart&#039;).addEventListener(&#039;click&#039;, restartGame);
    increaseLevelBtn.addEventListener(&#039;click&#039;, increaseLevel);
    decreaseLevelBtn.addEventListener(&#039;click&#039;, decreaseLevel);
    continueBtn.addEventListener(&#039;click&#039;, () =&gt; {
      gameOver = false;
      allowContinue = true;
      message.style.display = &#039;none&#039;;
      saveGame();
    });

    loadBest();
    init();
  &lt;/script&gt;</description>
            </item>
                    <item>
                <title>кубік рубіка 3 на 3</title>
                <link>http://margo.mozello.shop/blog3/params/post/5185431/kr3</link>
                <pubDate>Thu, 18 Dec 2025 17:15:00 +0000</pubDate>
                <description>дддддддддддддддддддддд&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;div class=&quot;rubik-cube-wrapper&quot; style=&quot;display: flex; justify-content: center; align-items: center; margin: 20px 0; position: relative; height: auto; min-height: 400px;&quot;&gt;
    &lt;style&gt;
        .rubik-cube-container {
            width: 400px; /* Змініть цей розмір для збільшення/зменшення */
            height: 419px; /* Висота повинна бути width + 19px для кнопок */
            background-color: #f0f0f0;
            border: 1px solid #ccc;
            padding: 10px;
            box-sizing: border-box;
        }
    &lt;/style&gt;
    &lt;script src=&quot;https://animcubejs.cubing.net/AnimCube3.js&quot;&gt;&lt;/script&gt;
    &lt;div class=&quot;rubik-cube-container&quot;&gt;
        &lt;script&gt;
            AnimCube3(&quot;move=RUR&#039;URU2R&#039;U2&amp;initrevmove=#&amp;edit=1&amp;demo=1&quot;);
        &lt;/script&gt;
    &lt;/div&gt;
&lt;/div&gt;</description>
            </item>
                    <item>
                <title>Лінії 098</title>
                <link>http://margo.mozello.shop/blog3/params/post/5164939/page</link>
                <pubDate>Mon, 03 Nov 2025 12:18:00 +0000</pubDate>
                <description>лллллллллллллллллллллллллллл&lt;hr class=&quot;moze-more-divider&quot;&gt;&lt;p&gt;98 2&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;title&gt;Lines 98 - Smaller Field for iOS&lt;/title&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0&quot;&gt;
  &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js&quot; onerror=&quot;loadBackupP5()&quot;&gt;&lt;/script&gt;
  &lt;script&gt;
    function loadBackupP5() {
      console.log(&quot;Failed to load p5.js from primary CDN, trying backup...&quot;);
      let script = document.createElement(&#039;script&#039;);
      script.src = &#039;https://unpkg.com/p5@1.4.2/lib/p5.min.js&#039;;
      script.onload = () =&gt; console.log(&quot;Backup p5.js loaded&quot;);
      script.onerror = () =&gt; console.log(&quot;Failed to load p5.js&quot;);
      document.head.appendChild(script);
    }
  &lt;/script&gt;
  &lt;style&gt;
    body { margin: 0; padding: 0; background: linear-gradient(to bottom, #e0f7fa, #b3e5fc); font-family: Arial, sans-serif; -webkit-user-select: none; user-select: none; display: flex; flex-direction: column; align-items: center; }
    #game-container { max-width: 100%; width: 100%; margin: 0 auto; padding: 5px; background: #fff; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.3); text-align: center; box-sizing: border-box; position: relative; }
    canvas { display: block; margin: 0 auto; border-radius: 8px; touch-action: none; cursor: pointer; width: 100%; max-height: 100vh; }
    .bottom-controls { display: flex; gap: 10px; margin-top: 10px; }
    button { padding: 6px 12px; background: #0288d1; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 12px; z-index: 10; }
    button:hover, button:active { background: #0277bd; }
    @media (max-width: 400px) { 
      #game-container { padding: 3px; } 
      button { padding: 5px 10px; font-size: 10px; } 
      canvas { max-width: 100%; max-height: calc(100vh - 10px); }
    }
  &lt;/style&gt;



  &lt;div id=&quot;game-container&quot;&gt;
  &lt;/div&gt;
  &lt;div class=&quot;bottom-controls&quot;&gt;
    &lt;button id=&quot;restart&quot; onclick=&quot;restartGame()&quot;&gt;Restart&lt;/button&gt;
    &lt;button id=&quot;hint&quot; onclick=&quot;showHint()&quot;&gt;Hint&lt;/button&gt;
  &lt;/div&gt;
    &lt;script&gt;
      let grid;
      let cellSize;
      let gridSize = 9;
      let colors = [&#039;#f44336&#039;, &#039;#2196f3&#039;, &#039;#4caf50&#039;, &#039;#ffeb3b&#039;, &#039;#9c27b0&#039;, &#039;#00bcd4&#039;, &#039;#ff9800&#039;];
      let selectedBall = null;
      let score = 0;
      let gameOver = false;
      let nextBalls = [];
      let animation = null;
      let moveCount = 0;
  
      function setup() {
        console.log(&quot;p5.js setup started&quot;);
        pixelDensity(2); // Support Retina display on iPhone 7
        let maxWidth = Math.min(window.innerWidth - 10, 320); // Smaller width for iPhone 7
        let maxHeight = Math.min(window.innerHeight - 10, 480); // Fit iPhone 7 height
        cellSize = Math.floor(maxWidth / gridSize);
        let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 100); // Reduced extra height
        let canvas = createCanvas(maxWidth, canvasHeight);
        canvas.parent(&#039;game-container&#039;);
        canvas.style(&#039;touch-action&#039;, &#039;none&#039;);
        console.log(`Canvas size: ${maxWidth}x${canvasHeight}, cellSize: ${cellSize}`);
        resetGame();
        console.log(&quot;p5.js setup completed&quot;);
      }
  
      function windowResized() {
        let maxWidth = Math.min(window.innerWidth - 10, 320);
        let maxHeight = Math.min(window.innerHeight - 10, 480);
        cellSize = Math.floor(maxWidth / gridSize);
        let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 100);
        resizeCanvas(maxWidth, canvasHeight);
        console.log(`Resized canvas: ${maxWidth}x${canvasHeight}`);
      }
  
      function resetGame() {
        grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
        nextBalls = generateBalls(3);
        spawnBalls(nextBalls);
        nextBalls = generateBalls(3);
        score = 0;
        gameOver = false;
        animation = null;
        selectedBall = null;
        moveCount = 0;
        console.log(&quot;Game reset&quot;);
      }
  
      function draw() {
        if (gameOver) {
          background(255);
          drawGrid();
          drawBalls();
          textAlign(CENTER);
          textSize(cellSize * 0.8);
          fill(255, 0, 0);
          text(&quot;Game Over!&quot;, width / 2, height / 2);
          return;
        }
  
        background(255);
        drawGrid();
        drawBalls();
        drawNextBalls();
        drawScore();
  
        if (animation) {
          let { startX, startY, endX, endY, color, progress } = animation;
          let x = lerp(startX, endX, progress);
          let y = lerp(startY, endY, progress);
          drawBall(x, y, color);
          animation.progress += 0.05;
          if (animation.progress &gt;= 1) animation = null;
        }
      }
  
      function drawGrid() {
        stroke(200);
        for (let i = 0; i &lt;= gridSize; i++) {
          line(i * cellSize, 0, i * cellSize, gridSize * cellSize);
          line(0, i * cellSize, gridSize * cellSize, i * cellSize);
        }
      }
  
      function drawBalls() {
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (grid[i][j]) {
              drawBall(j * cellSize + cellSize / 2, i * cellSize + cellSize / 2, grid[i][j]);
            }
          }
        }
        if (selectedBall) {
          noFill();
          stroke(0);
          strokeWeight(2);
          rect(selectedBall.j * cellSize, selectedBall.i * cellSize, cellSize, cellSize);
        }
      }
  
      function drawBall(x, y, color) {
        fill(color);
        noStroke();
        ellipse(x, y, cellSize * 0.8);
      }
  
      function drawNextBalls() {
        textAlign(LEFT);
        textSize(14);
        fill(0);
        text(&quot;Next:&quot;, 10, gridSize * cellSize + 20);
        for (let i = 0; i &lt; nextBalls.length; i++) {
          drawBall(60 + i * cellSize / 2, gridSize * cellSize + 20, nextBalls[i]);
        }
      }
  
      function drawScore() {
        textAlign(RIGHT);
        textSize(14);
        fill(0);
        text(`Score: ${score}`, width - 10, gridSize * cellSize + 20);
      }
  
      function generateBalls(count) {
        return Array(count).fill().map(() =&gt; random(colors));
      }
  
      function spawnBalls(balls) {
        for (let color of balls) {
          let emptyCells = getEmptyCells();
          if (emptyCells.length === 0) {
            gameOver = true;
            return;
          }
          let pos = random(emptyCells);
          grid[pos.i][pos.j] = color;
        }
      }

      function getEmptyCells() {
        let emptyCells = [];
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (!grid[i][j]) emptyCells.push({ i, j });
          }
        }
        return emptyCells;
      }
  
      function mousePressed() {
        if (gameOver || animation) return;
        let i = floor(mouseY / cellSize);
        let j = floor(mouseX / cellSize);
        if (i &gt;= 0 &amp;&amp; i &lt; gridSize &amp;&amp; j &gt;= 0 &amp;&amp; j &lt; gridSize) {
          if (grid[i][j]) {
            selectedBall = { i, j };
          } else if (selectedBall) {
            if (canMove(selectedBall.i, selectedBall.j, i, j)) {
              animateMove(selectedBall.i, selectedBall.j, i, j);
              moveBall(selectedBall.i, selectedBall.j, i, j);
              let lines = checkLines();
              if (lines.length &gt; 0) {
                removeLines(lines);
              } else {
                spawnBalls(nextBalls);
                nextBalls = generateBalls(3);
              }
              selectedBall = null;
              moveCount++;
              if (isGridFull()) gameOver = true;
            }
          }
        }
      }
  
      function animateMove(startI, startJ, endI, endJ) {
        animation = {
          startX: startJ * cellSize + cellSize / 2,
          startY: startI * cellSize + cellSize / 2,
          endX: endJ * cellSize + cellSize / 2,
          endY: endI * cellSize + cellSize / 2,
          color: grid[startI][startJ],
          progress: 0
        };
      }
  
      function canMove(startI, startJ, endI, endJ) {
        if (startI === endI &amp;&amp; startJ === endJ) return false;
        let queue = [{ i: startI, j: startJ }];
        let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
        visited[startI][startJ] = true;
        let maxIterations = gridSize * gridSize;
        let iterations = 0;
  
        while (queue.length &gt; 0) {
          iterations++;
          if (iterations &gt; maxIterations) {
            console.log(&quot;canMove: Max iterations reached&quot;);
            return false;
          }
          let { i, j } = queue.shift();
          if (i === endI &amp;&amp; j === endJ) return true;
  
          let neighbors = [
            { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
            { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
          ];
  
          for (let { ni, nj } of neighbors) {
            if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
              queue.push({ i: ni, j: nj });
              visited[ni][nj] = true;
            }
          }
        }
        return false;
      }
  
      function isAnyMovePossible() {
        for (let si = 0; si &lt; gridSize; si++) {
          for (let sj = 0; sj &lt; gridSize; sj++) {
            if (grid[si][sj]) {
              let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
              let queue = [{ i: si, j: sj }];
              visited[si][sj] = true;
              while (queue.length &gt; 0) {
                let { i, j } = queue.shift();
                let neighbors = [
                  { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
                  { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
                ];
                for (let { ni, nj } of neighbors) {
                  if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
                    return true;
                  }
                }
              }
            }
          }
        }
        return false;
      }
  
      function moveBall(startI, startJ, endI, endJ) {
        grid[endI][endJ] = grid[startI][startJ];
        grid[startI][startJ] = null;
      }
  
      function copyGrid(g) {
        return g.map(row =&gt; row.slice());
      }

      function checkLine(startI, startJ, di, dj, customGrid = grid) {
        let line = [{ i: startI, j: startJ }];
        let color = customGrid[startI][startJ];
        let i = startI + di;
        let j = startJ + dj;
        let iterations = 0;
        let maxIterations = gridSize;
        while (i &gt;= 0 &amp;&amp; i &lt; gridSize &amp;&amp; j &gt;= 0 &amp;&amp; j &lt; gridSize &amp;&amp; customGrid[i][j] === color) {
          iterations++;
          if (iterations &gt; maxIterations) {
            console.log(&quot;checkLine: Max iterations reached&quot;);
            break;
          }
          line.push({ i, j });
          i += di;
          j += dj;
        }
        return line;
      }

      function checkLines(customGrid = grid) {
        let lines = [];
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (customGrid[i][j]) {
              let hLine = checkLine(i, j, 0, 1, customGrid);
              if (hLine.length &gt;= 5) lines.push(hLine);
              let vLine = checkLine(i, j, 1, 0, customGrid);
              if (vLine.length &gt;= 5) lines.push(vLine);
              let d1Line = checkLine(i, j, 1, -1, customGrid);
              if (d1Line.length &gt;= 5) lines.push(d1Line);
              let d2Line = checkLine(i, j, 1, 1, customGrid);
              if (d2Line.length &gt;= 5) lines.push(d2Line);
            }
          }
        }
        let uniqueLines = [];
        let removed = new Set();
        for (let line of lines) {
          let positions = line.map(p =&gt; `${p.i},${p.j}`);
          if (!positions.some(pos =&gt; removed.has(pos))) {
            uniqueLines.push(line);
            positions.forEach(pos =&gt; removed.add(pos));
          }
        }
        return uniqueLines;
      }
  
      function removeLines(lines) {
        for (let line of lines) {
          for (let { i, j } of line) {
            grid[i][j] = null;
          }
          score += line.length * 2;
        }
      }
  
      function isGridFull() {
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (!grid[i][j]) return false;
          }
        }
        return true;
      }

      function findHelpfulMove() {
        for (let si = 0; si &lt; gridSize; si++) {
          for (let sj = 0; sj &lt; gridSize; sj++) {
            if (grid[si][sj]) {
              for (let ei = 0; ei &lt; gridSize; ei++) {
                for (let ej = 0; ej &lt; gridSize; ej++) {
                  if (!grid[ei][ej] &amp;&amp; canMove(si, sj, ei, ej)) {
                    let tempGrid = copyGrid(grid);
                    tempGrid[ei][ej] = tempGrid[si][sj];
                    tempGrid[si][sj] = null;
                    let lines = checkLines(tempGrid);
                    if (lines.length &gt; 0) {
                      return { from: { i: si, j: sj }, to: { i: ei, j: ej } };
                    }
                  }
                }
              }
            }
          }
        }
        return null;
      }

      function showHint() {
        if (gameOver) {
          alert(&quot;Game is over!&quot;);
          return;
        }
        let move = findHelpfulMove();
        if (move) {
          alert(`Move ball from row ${move.from.i + 1}, col ${move.from.j + 1} to row ${move.to.i + 1}, col ${move.to.j + 1}`);
        } else {
          alert(&quot;No immediate line-forming move found.&quot;);
        }
      }
  
      function restartGame() {
        resetGame();
        console.log(&quot;Game restarted via button&quot;);
      }
    &lt;/script&gt;</description>
            </item>
                    <item>
                <title>день 1</title>
                <link>http://margo.mozello.shop/blog3/params/post/5160527/den-1</link>
                <pubDate>Wed, 22 Oct 2025 21:17:00 +0000</pubDate>
                <description>шшшшшшшшшшшшшшшшшшшшшшшшшшш&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;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»&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 20px;
            text-align: center;
        }
        .container {
            max-width: 1600px;
            margin: auto;
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        h1 {
            color: #333;
        }
        .scenario {
            margin: 20px 0;
        }
        button {
            background-color: #4CAF50;
            color: white;
            padding: 10px 20px;
            margin: 10px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
        button:hover {
            background-color: #45a049;
        }
        #feedback {
            margin-top: 20px;
            font-weight: bold;
        }
        #score {
            font-size: 24px;
            color: #007BFF;
        }
        #replay {
            display: none;
        }
    &lt;/style&gt;


    &lt;div class=&quot;container&quot;&gt;
        &lt;h1&gt;Симулятор мислення «Дня 1»&lt;/h1&gt;
        &lt;p&gt;Ви — CEO зростаючого IT-стартапу. Приймайте рішення, щоб залишатися в режимі &#039;Дня 1&#039;!&lt;/p&gt;
        &lt;div id=&quot;game&quot;&gt;&lt;/div&gt;
        &lt;div id=&quot;feedback&quot;&gt;&lt;/div&gt;
        &lt;div id=&quot;score&quot;&gt;&lt;/div&gt;
        &lt;button id=&quot;replay&quot; onclick=&quot;startGame()&quot;&gt;Грати знову&lt;/button&gt;
    &lt;/div&gt;

    &lt;script&gt;
        const scenarios = [
            {
                prompt: &quot;Сценарій: Ваша команда помітила, що конкурент запустив нову функцію. На чому зосередитися?&quot;,
                options: [
                    { text: &quot;Вивчити конкурента&quot;, value: &quot;competitor&quot;, feedback: &quot;Це День 2. -5 очок.&quot; },
                    { text: &quot;Опитати клієнтів&quot;, value: &quot;client&quot;, feedback: &quot;Чудово! +10 очок.&quot; },
                    { text: &quot;Ігнорувати&quot;, value: &quot;ignore&quot;, feedback: &quot;Ризик стагнації. -5 очок.&quot; }
                ],
                correct: &quot;client&quot;
            },
            {
                prompt: &quot;Сценарій: Вирішення щодо нового техстеку з 70% даних. Що робити?&quot;,
                options: [
                    { text: &quot;Чекати 100%&quot;, value: &quot;wait&quot;, feedback: &quot;Затримки ведуть до Дня 2. -5 очок.&quot; },
                    { text: &quot;Вирішити зараз&quot;, value: &quot;decide&quot;, feedback: &quot;Швидка дія! +10 очок.&quot; },
                    { text: &quot;Сформувати комітет&quot;, value: &quot;committee&quot;, feedback: &quot;Пастка бюрократії. -5 очок.&quot; }
                ],
                correct: &quot;decide&quot;
            },
            {
                prompt: &quot;Сценарій: Занадто багато зустрічей уповільнюють розробку. Як виправити?&quot;,
                options: [
                    { text: &quot;Додати більше зустрічей&quot;, value: &quot;more meetings&quot;, feedback: &quot;Гірше! -5 очок.&quot; },
                    { text: &quot;Спростити процеси&quot;, value: &quot;simplify&quot;, feedback: &quot;Аджайл-рух. +10 очок.&quot; },
                    { text: &quot;Ігнорувати&quot;, value: &quot;ignore&quot;, feedback: &quot;Процеси понад результати. -5 очок.&quot; }
                ],
                correct: &quot;simplify&quot;
            },
            {
                prompt: &quot;Сценарій: Виникає новий тренд ШІ. Реакція?&quot;,
                options: [
                    { text: &quot;Опір&quot;, value: &quot;resist&quot;, feedback: &quot;Нерелевантність попереду. -5 очок.&quot; },
                    { text: &quot;Експериментувати&quot;, value: &quot;experiment&quot;, feedback: &quot;Приймайте тренди! +10 очок.&quot; },
                    { text: &quot;Чекати конкурентів&quot;, value: &quot;wait competitors&quot;, feedback: &quot;Втрачена можливість. -5 очок.&quot; }
                ],
                correct: &quot;experiment&quot;
            },
            {
                prompt: &quot;Сценарій: Баг у продакшні. Команда хоче повний аналіз спочатку. Ви?&quot;,
                options: [
                    { text: &quot;Повний аналіз&quot;, value: &quot;full analysis&quot;, feedback: &quot;Занадто повільно. -5 очок.&quot; },
                    { text: &quot;Швидке виправлення&quot;, value: &quot;quick fix&quot;, feedback: &quot;Висока швидкість! +10 очок.&quot; },
                    { text: &quot;Скликати зустріч&quot;, value: &quot;meeting&quot;, feedback: &quot;Пастка посередників. -5 очок.&quot; }
                ],
                correct: &quot;quick fix&quot;
            },
            {
                prompt: &quot;Сценарій: Зворотний зв&#039;язок клієнта щодо UI додатка. Пріоритезувати?&quot;,
                options: [
                    { text: &quot;Внутрішні метрики&quot;, value: &quot;internal metrics&quot;, feedback: &quot;Фокус Дня 2. -5 очок.&quot; },
                    { text: &quot;Потреби клієнта&quot;, value: &quot;client needs&quot;, feedback: &quot;Одержимість клієнтом! +10 очок.&quot; },
                    { text: &quot;Затримати зміни&quot;, value: &quot;delay&quot;, feedback: &quot;Стагнація. -5 очок.&quot; }
                ],
                correct: &quot;client needs&quot;
            }
        ];

        let currentScenario = 0;
        let score = 0;
        let shuffledScenarios = [];

        function shuffle(array) {
            return array.sort(() =&gt; Math.random() - 0.5);
        }

        function startGame() {
            currentScenario = 0;
            score = 0;
            shuffledScenarios = shuffle([...scenarios]).slice(0, 4); // 4 випадкових сценарії
            document.getElementById(&#039;feedback&#039;).innerHTML = &#039;&#039;;
            document.getElementById(&#039;score&#039;).innerHTML = &#039;&#039;;
            document.getElementById(&#039;replay&#039;).style.display = &#039;none&#039;;
            showScenario();
        }

        function showScenario() {
            const gameDiv = document.getElementById(&#039;game&#039;);
            gameDiv.innerHTML = `&lt;p class=&quot;scenario&quot;&gt;${shuffledScenarios[currentScenario].prompt}&lt;/p&gt;`;
            shuffledScenarios[currentScenario].options.forEach(opt =&gt; {
                const btn = document.createElement(&#039;button&#039;);
                btn.innerText = opt.text;
                btn.onclick = () =&gt; handleChoice(opt.value);
                gameDiv.appendChild(btn);
            });
        }

        function handleChoice(choice) {
            const scenario = shuffledScenarios[currentScenario];
            let feedbackText = &#039;Неправильний вибір.&#039;;
            let points = 0;
            const opt = scenario.options.find(o =&gt; o.value === choice);
            if (opt) {
                feedbackText = opt.feedback;
                points = (choice === scenario.correct) ? 10 : -5;
            }
            score += points;
            document.getElementById(&#039;feedback&#039;).innerHTML = feedbackText;

            currentScenario++;
            if (currentScenario &lt; shuffledScenarios.length) {
                setTimeout(showScenario, 1500); // Коротка затримка для фідбеку
            } else {
                endGame();
            }
        }

        function endGame() {
            document.getElementById(&#039;game&#039;).innerHTML = &#039;&#039;;
            document.getElementById(&#039;feedback&#039;).innerHTML = &#039;&#039;;
            document.getElementById(&#039;score&#039;).innerHTML = `Ваш рахунок: ${score}/40`;
            let message = &#039;&#039;;
            if (score &gt;= 30) message = &quot;Майстер Дня 1! 🎉&quot;;
            else if (score &gt;= 20) message = &quot;Добре, але вдоскональте ваше мислення.&quot;;
            else message = &quot;Уникайте пасток Дня 2!&quot;;
            document.getElementById(&#039;feedback&#039;).innerHTML = message;
            document.getElementById(&#039;replay&#039;).style.display = &#039;block&#039;;
        }

        startGame(); // Запустити гру автоматично
    &lt;/script&gt;</description>
            </item>
                    <item>
                <title>Тренажер: Збір (переміщення) стопки книг</title>
                <link>http://margo.mozello.shop/blog3/params/post/5138926/julotijuo</link>
                <pubDate>Sat, 27 Sep 2025 12:29:00 +0000</pubDate>
                <description>оооооооооооооооооооооооо
&lt;hr class=&quot;moze-more-divider&quot;&gt;
&lt;p&gt;1&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&quot;&gt;
  &lt;title&gt;Тренажер: Збір стопки книг (Розвиток змістової пам&#039;яті)&lt;/title&gt;
  &lt;style&gt;
    :root {
      --bg: #f5e6d3; /* Бежевий фон як на малюнку */
      --shelf-bg: #ffffff; /* Білі полички */
      --shelf-shadow: rgba(0,0,0,0.15);
      --book-h: 30px; /* Висота книг, зменшена для кращого вигляду */
      --font: &quot;Segoe UI&quot;, Roboto, Arial;
    }
    * { box-sizing: border-box; }
    body {
      margin: 0;
      font-family: var(--font);
      background: var(--bg);
      min-height: 100vh;
      color: #111;
      display: flex;
      align-items: flex-start;
      justify-content: center;
      padding: 20px;
      position: relative;
    }
    .game { width: 100%; max-width: 1500px; position: relative; }
    header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; color: #333; }
    header h1 { margin: 0; font-size: 20px; }
    .controls { display: flex; gap: 12px; align-items: center; }
    .controls button { padding: 6px 12px; border-radius: 6px; border: none; cursor: pointer; font-weight: 600; background: #4CAF50; color: white; }
    .controls .stat { color: #333; font-size: 14px; }

    .wall-decor {
      position: absolute;
      top: 20px;
      left: 20px;
      width: 40px;
      height: 30px;
      background: #e0d0b0; /* Картина на стіні */
      border: 2px solid #d0b080;
      z-index: -1;
    }

    .shelves { display: flex; justify-content: space-around; margin-bottom: 24px; position: relative; }
    .shelf { width: 180px; height: 250px; background: var(--shelf-bg); border-radius: 4px; box-shadow: 0 2px 4px var(--shelf-shadow); position: relative; display: flex; flex-direction: column-reverse; align-items: center; padding-bottom: 10px; gap: 2px; /* Додано gap для проміжків між книгами */ }
    .shelf::before { content: &#039;&#039;; position: absolute; bottom: -5px; width: 100%; height: 5px; background: #d0d0d0; } /* Тінь під полицею */

    .shelf:nth-child(1)::after { 
      content: &#039;🌵&#039;; /* Кактус на нижній полиці */
      position: absolute;
      bottom: 10px;
      left: 10px;
      font-size: 24px;
    }
    .shelf:nth-child(2)::after { 
      content: &#039;🌸&#039;; /* Квітка на середній */
      position: absolute;
      bottom: 10px;
      right: 10px;
      font-size: 24px;
    }
    .shelf:nth-child(3)::after { 
      content: &#039;📖&#039;; /* Декор на верхній */
      position: absolute;
      top: 10px;
      left: 10px;
      font-size: 20px;
    }

    .book {
      height: var(--book-h);
      border-radius: 4px;
      box-shadow: 0 2px 4px var(--shelf-shadow);
      cursor: grab;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-weight: bold;
      transition: transform 0.2s;
      user-select: none; /* Додано, щоб уникнути виділення тексту */
    }
    .book.extra-large { width: 160px; background: linear-gradient(180deg, #ff4500, #d2691e); } /* Помаранчева велика */
    .book.large { width: 120px; background: linear-gradient(180deg, #32cd32, #228b22); } /* Зелена */
    .book.medium { width: 80px; background: linear-gradient(180deg, #ff0000, #b22222); } /* Червона */
    .book.small { width: 40px; background: linear-gradient(180deg, #1e90ff, #4169e1); } /* Синя для різноманітності */

    .arrow { 
      position: absolute;
      top: 100px;
      left: 50%;
      transform: translateX(-50%);
      font-size: 40px;
      color: #ff69b4; /* Рожева стрілка вниз */
      pointer-events: none;
      animation: fall 1s infinite;
    }
    @keyframes fall {
      0% { transform: translateY(0); }
      50% { transform: translateY(10px); }
      100% { transform: translateY(0); }
    }

    .drag-layer {
      position: fixed; left: 0; top: 0; pointer-events: none; z-index: 9999;
    }
    .drag-layer .book { position: relative; left: 0; top: 0; }

    .overlay { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,0.4); }
    .overlay.hidden { display: none; }
    .overlay-content { background: #fff; padding: 20px; border-radius: 10px; text-align: center; }
  &lt;/style&gt;



  &lt;div class=&quot;game&quot;&gt;
    &lt;header&gt;
      &lt;h1&gt;Тренажер: Збір стопки книг&lt;/h1&gt;
      &lt;div class=&quot;controls&quot;&gt;
        &lt;button id=&quot;newGameBtn&quot; fdprocessedid=&quot;6mivbe&quot;&gt;Нова гра&lt;/button&gt;
        &lt;div class=&quot;stat&quot;&gt;Ходи:
          &lt;span id=&quot;moves&quot;&gt;0&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/header&gt;

    &lt;div class=&quot;wall-decor&quot;&gt;&lt;/div&gt;
    &lt;!-- Картина на стіні --&gt;

    &lt;main&gt;
      &lt;div class=&quot;shelves&quot;&gt;
        &lt;div class=&quot;shelf&quot; data-index=&quot;0&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;shelf&quot; data-index=&quot;1&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;shelf&quot; data-index=&quot;2&quot;&gt;&lt;/div&gt;
      &lt;/div&gt;
      &lt;div class=&quot;arrow&quot;&gt;↓&lt;/div&gt;
      &lt;!-- Анімована стрілка вниз --&gt;
    &lt;/main&gt;

    &lt;div id=&quot;winOverlay&quot; class=&quot;overlay hidden&quot;&gt;
      &lt;div class=&quot;overlay-content&quot;&gt;
        &lt;h2&gt;Вітаю — перемога! 🎉&lt;/h2&gt;
        &lt;p&gt;Ходи:
          &lt;span id=&quot;winMoves&quot;&gt;0&lt;/span&gt;
        &lt;/p&gt;
        &lt;button id=&quot;closeWin&quot;&gt;Ще раз&lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;script&gt;
    (() =&gt; {
      const SIZES = [&#039;extra-large&#039;, &#039;large&#039;, &#039;medium&#039;, &#039;small&#039;]; // Розміри книг
      let shelves = [[], [], []]; // Три полиці
      let moves = 0;
      let dragState = null;

      const shelvesEls = document.querySelectorAll(&#039;.shelf&#039;);
      const movesEl = document.getElementById(&#039;moves&#039;);
      const winOverlay = document.getElementById(&#039;winOverlay&#039;);
      const winMoves = document.getElementById(&#039;winMoves&#039;);
      const newGameBtn = document.getElementById(&#039;newGameBtn&#039;);
      const closeWin = document.getElementById(&#039;closeWin&#039;);

      function newGame(numBooks = 4) {
        shelves = [[], [], []];
        moves = 0;
        renderMoves();

        // Створюємо книги та розміщуємо на першій полиці (зверху найменша)
        for (let i = 0; i &lt; numBooks; i++) {
          shelves[0].push({ size: SIZES[i] });
        }
        renderAll();
      }

      function renderAll() {
        shelvesEls.forEach((el, idx) =&gt; {
          el.innerHTML = &#039;&#039;;
          shelves[idx].forEach((book, bookIdx) =&gt; {
            const bookEl = createBookEl(book);
            el.appendChild(bookEl);
            bookEl.addEventListener(&#039;pointerdown&#039;, (e) =&gt; beginDrag(e, idx, bookIdx));
          });
        });
        checkWin();
      }

      function createBookEl(book) {
        const el = document.createElement(&#039;div&#039;);
        el.className = `book ${book.size}`;
        el.textContent = book.size.charAt(0).toUpperCase();
        return el;
      }

      function renderMoves() {
        movesEl.textContent = moves;
      }

      function beginDrag(e, shelfIdx, bookIdx) {
        e.preventDefault(); // Додано, щоб уникнути дефолтної поведінки
        if (bookIdx !== shelves[shelfIdx].length - 1) return;

        const seq = [shelves[shelfIdx].pop()];
        dragState = { shelfIdx, seq, layer: null, ox: e.clientX, oy: e.clientY, dx: 0, dy: 0, dragging: false };

        const move = ev =&gt; {
          if (!dragState.dragging &amp;&amp; Math.abs(ev.clientX - dragState.ox) + Math.abs(ev.clientY - dragState.oy) &gt; 5) {
            startDrag(ev);
          }
          if (dragState.dragging) updateDrag(ev);
        };
        const up = ev =&gt; {
          window.removeEventListener(&#039;pointermove&#039;, move);
          window.removeEventListener(&#039;pointerup&#039;, up);
          endDrag(ev);
        };
        window.addEventListener(&#039;pointermove&#039;, move);
        window.addEventListener(&#039;pointerup&#039;, up);
      }

      function startDrag(e) {
        dragState.dragging = true;
        const layer = document.createElement(&#039;div&#039;);
        layer.className = &#039;drag-layer&#039;;
        document.body.append(layer);
        dragState.layer = layer;

        dragState.seq.forEach(book =&gt; {
          const el = createBookEl(book);
          layer.append(el);
        });
        updateDrag(e);
      }

      function updateDrag(e) {
        dragState.dx = e.clientX - 40;
        dragState.dy = e.clientY - 40;
        dragState.layer.style.transform = `translate(${dragState.dx}px, ${dragState.dy}px)`;
      }

      function endDrag(e) {
        if (!dragState.dragging) {
          dragState = null;
          return;
        }
        if (dragState.layer) dragState.layer.style.pointerEvents = &#039;none&#039;;
        const elems = document.elementsFromPoint(e.clientX, e.clientY);
        if (dragState.layer) dragState.layer.style.pointerEvents = &#039;&#039;;

        let dropped = false;
        const targetShelf = elems.find(el =&gt; el.classList &amp;&amp; el.classList.contains(&#039;shelf&#039;));
        if (targetShelf) {
          const targetIdx = parseInt(targetShelf.dataset.index);
          if (targetIdx !== dragState.shelfIdx) {
            dropped = tryToShelf(dragState.seq[0], targetIdx);
          }
        }

        if (!dropped) {
          shelves[dragState.shelfIdx].push(dragState.seq[0]);
        } else {
          moves++;
          renderMoves();
        }

        if (dragState.layer) dragState.layer.remove();
        dragState = null;
        renderAll();
      }

      function tryToShelf(book, targetIdx) {
        const targetStack = shelves[targetIdx];
        if (targetStack.length === 0 || SIZES.indexOf(book.size) &gt; SIZES.indexOf(targetStack[targetStack.length - 1].size)) {
          targetStack.push(book);
          return true;
        }
        return false;
      }

      function checkWin() {
        if (shelves[2].length === SIZES.length) {
          winMoves.textContent = moves;
          winOverlay.classList.remove(&#039;hidden&#039;);
        }
      }

      newGameBtn.onclick = () =&gt; { winOverlay.classList.add(&#039;hidden&#039;); newGame(); };
      closeWin.onclick = () =&gt; { winOverlay.classList.add(&#039;hidden&#039;); newGame(); };

      newGame();
    })();
  &lt;/script&gt;</description>
            </item>
                    <item>
                <title>11</title>
                <link>http://margo.mozello.shop/blog3/params/post/5137115/11</link>
                <pubDate>Tue, 23 Sep 2025 12:54:00 +0000</pubDate>
                <description>оооооооооооооооооооооооооооооо&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;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.3&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 {
            font-size: 20px;
            margin-top: 10px;
        }
        #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;
        }
        #blockTable {
            width: 100%;
            max-width: 500px;
            border-collapse: collapse;
            margin-bottom: 15px;
        }
        #blockTable th, #blockTable td {
            border: 1px solid #333;
            padding: 8px;
            text-align: center;
        }
        #blockTable th {
            background-color: #ddd;
        }
        #blockTable canvas {
            border: 1px solid #ccc;
        }
    &lt;/style&gt;


    &lt;table id=&quot;blockTable&quot;&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;/tbody&gt;
    &lt;/table&gt;
    &lt;h2&gt;Блоки Легенда — Версія 1.3&lt;/h2&gt;
    &lt;p&gt;Права кнопка миші — поворот блоку, Середня кнопка/подвійне торкання — перевертання, Кнопка &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;j7xyhz&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;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;script&gt;
        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 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 currentBlocks = [];
        let selectedBlock = null;
        let gameActive = true;
        let gamePaused = false;
        let lastMove = null;

        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)
        ];

        const colors = [&#039;#FF0000&#039;, &#039;#00FF00&#039;, &#039;#0000FF&#039;, &#039;#FFFF00&#039;, &#039;#FF00FF&#039;, &#039;#FFA500&#039;, &#039;#800080&#039;];

        function rotateShape(shape) {
            const rows = shape.length;
            const cols = shape[0].length;
            const newShape = 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++) {
                    newShape[x][rows - 1 - y] = shape[y][x];
                }
            }
            return newShape;
        }

        function flipShape(shape) {
            const newShape = shape.map(row =&gt; [...row].reverse());
            return newShape;
        }

        function undoMove() {
            if (!lastMove || !gameActive || gamePaused) return;
            const { grid: prevGrid, score: prevScore, block, blockIndex } = lastMove;
            grid = prevGrid.map(row =&gt; [...row]);
            score = prevScore;
            scoreElement.textContent = `Очки: ${score}`;
            currentBlocks.splice(blockIndex, 0, block);
            for (let i = 0; i &lt; 3; i++) {
                if (i &lt; currentBlocks.length) {
                    drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                } else {
                    document.getElementById(`block${i + 1}`).getContext(&#039;2d&#039;).clearRect(0, 0, 80, 80);
                }
            }
            lastMove = null;
            undoButton.disabled = true;
            drawGrid();
            console.log(&#039;Хід скасовано&#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]);

        function generateBlocks() {
            console.log(&#039;Генеруються нові блоки, поточна кількість:&#039;, currentBlocks.length);
            currentBlocks = [];
            for (let i = 1; i &lt;= 3; i++) {
                document.getElementById(`block${i}`).getContext(&#039;2d&#039;).clearRect(0, 0, 80, 80);
            }
            for (let i = 0; i &lt; 3; i++) {
                const shapeIndex = Math.floor(Math.random() * blockShapes.length);
                const color = colors[Math.floor(Math.random() * colors.length)];
                currentBlocks.push({ shape: blockShapes[shapeIndex], color });
                drawBlock(i, blockShapes[shapeIndex], color);
                console.log(`Згенеровано блок ${i + 1}: форма ${JSON.stringify(blockShapes[shapeIndex])}, колір ${color}`);
            }
            console.log(&#039;Нові блоки створено:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
            drawGrid();
        }

        function drawBlock(index, shape, color) {
            const blockCanvas = document.getElementById(`block${index + 1}`);
            const blockCtx = blockCanvas.getContext(&#039;2d&#039;);
            blockCtx.clearRect(0, 0, blockCanvas.width, blockCanvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = Math.min(blockCanvas.width / maxSize, blockCanvas.height / maxSize) * 0.9;
            const offsetX = (blockCanvas.width - maxSize * blockCellSize) / 2;
            const offsetY = (blockCanvas.height - maxSize * 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 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) {
                score += linesCleared * 100;
                scoreElement.textContent = `Очки: ${score}`;
            }
            console.log(&#039;Очищено ліній:&#039;, linesCleared, &#039;Очки:&#039;, score);
        }

        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;
                finalScoreElement.textContent = `Ваш рахунок: ${score}`;
                gameOverElement.style.display = &#039;block&#039;;
                console.log(&#039;Гра закінчена. Рахунок:&#039;, score);
            }
        }

        function restartGame() {
            grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
            score = 0;
            scoreElement.textContent = `Очки: ${score}`;
            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;);
        }

        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;
                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.3&#039;);
    &lt;/script&gt;</description>
            </item>
                    <item>
                <title>9</title>
                <link>http://margo.mozello.shop/blog3/params/post/5137035/9</link>
                <pubDate>Tue, 23 Sep 2025 10:08:00 +0000</pubDate>
                <description>&lt;title&gt;Lines 98 - Smaller Field for iOS&lt;/title&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0&quot;&gt;
  &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js&quot; onerror=&quot;loadBackupP5()&quot;&gt;&lt;/script&gt;
  &lt;script&gt;
    function loadBackupP5() {
      console.log(&quot;Failed to load p5.js from primary CDN, trying backup...&quot;);
      let script = document.createElement(&#039;script&#039;);
      script.src = &#039;https://unpkg.com/p5@1.4.2/lib/p5.min.js&#039;;
      script.onload = () =&gt; console.log(&quot;Backup p5.js loaded&quot;);
      script.onerror = () =&gt; console.log(&quot;Failed to load p5.js&quot;);
      document.head.appendChild(script);
    }
  &lt;/script&gt;
  &lt;style&gt;
    body { margin: 0; padding: 0; background: linear-gradient(to bottom, #e0f7fa, #b3e5fc); font-family: Arial, sans-serif; -webkit-user-select: none; user-select: none; }
    #game-container { max-width: 100%; width: 100%; margin: 0 auto; padding: 5px; background: #fff; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.3); text-align: center; box-sizing: border-box; position: relative; }
    canvas { display: block; margin: 0 auto; border-radius: 8px; touch-action: none; cursor: pointer; width: 100%; max-height: 100vh; }
    #restart { position: absolute; top: 5px; right: 5px; padding: 6px 12px; background: #0288d1; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 12px; z-index: 10; }
    #restart:hover, #restart:active { background: #0277bd; }
    @media (max-width: 400px) { 
      #game-container { padding: 3px; } 
      #restart { padding: 5px 10px; font-size: 10px; } 
      canvas { max-width: 100%; max-height: calc(100vh - 10px); }
    }
  &lt;/style&gt;



  &lt;div id=&quot;game-container&quot;&gt;
    &lt;button id=&quot;restart&quot; onclick=&quot;restartGame()&quot; fdprocessedid=&quot;1ze84&quot;&gt;Restart&lt;/button&gt;
    &lt;script&gt;
      let grid;
      let cellSize;
      let gridSize = 9;
      let colors = [&#039;#f44336&#039;, &#039;#2196f3&#039;, &#039;#4caf50&#039;, &#039;#ffeb3b&#039;, &#039;#9c27b0&#039;, &#039;#00bcd4&#039;, &#039;#ff9800&#039;];
      let selectedBall = null;
      let score = 0;
      let gameOver = false;
      let nextBalls = [];
      let animation = null;
      let moveCount = 0;
  
      function setup() {
        console.log(&quot;p5.js setup started&quot;);
        pixelDensity(2); // Support Retina display on iPhone 7
        let maxWidth = Math.min(window.innerWidth - 10, 320); // Smaller width for iPhone 7
        let maxHeight = Math.min(window.innerHeight - 10, 480); // Fit iPhone 7 height
        cellSize = Math.floor(maxWidth / gridSize);
        let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 100); // Reduced extra height
        let canvas = createCanvas(maxWidth, canvasHeight);
        canvas.parent(&#039;game-container&#039;);
        canvas.style(&#039;touch-action&#039;, &#039;none&#039;);
        console.log(`Canvas size: ${maxWidth}x${canvasHeight}, cellSize: ${cellSize}`);
        resetGame();
        console.log(&quot;p5.js setup completed&quot;);
      }
  
      function windowResized() {
        let maxWidth = Math.min(window.innerWidth - 10, 320);
        let maxHeight = Math.min(window.innerHeight - 10, 480);
        cellSize = Math.floor(maxWidth / gridSize);
        let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 100);
        resizeCanvas(maxWidth, canvasHeight);
        console.log(`Resized canvas: ${maxWidth}x${canvasHeight}`);
      }
  
      function resetGame() {
        grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
        nextBalls = generateBalls(3);
        spawnBalls(nextBalls);
        nextBalls = generateBalls(3);
        score = 0;
        gameOver = false;
        animation = null;
        selectedBall = null;
        moveCount = 0;
        console.log(&quot;Game reset&quot;);
      }
  
      function draw() {
        if (gameOver) {
          background(255);
          drawGrid();
          drawBalls();
          textAlign(CENTER);
          textSize(cellSize * 0.8);
          fill(255, 0, 0);
          text(&quot;Game Over!&quot;, width / 2, height / 2);
          return;
        }
  
        background(255);
        drawGrid();
        drawBalls();
        drawNextBalls();
        drawScore();
  
        if (animation) {
          let { startX, startY, endX, endY, color, progress } = animation;
          let x = lerp(startX, endX, progress);
          let y = lerp(startY, endY, progress);
          drawBall(-1, -1, color, x, y);
          animation.progress += 0.05;
          if (animation.progress &gt;= 1) {
            animation = null;
          }
        }
      }
  
      function drawGrid() {
        fill(240, 240, 240);
        rect(10, 10, gridSize * cellSize, gridSize * cellSize, 5);
        stroke(200);
        strokeWeight(1);
        for (let i = 0; i &lt;= gridSize; i++) {
          line(10 + i * cellSize, 10, 10 + i * cellSize, 10 + gridSize * cellSize);
          line(10, 10 + i * cellSize, 10 + gridSize * cellSize, 10 + i * cellSize);
        }
      }
  
      function drawBalls() {
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (grid[i][j]) {
              drawBall(i, j, grid[i][j]);
            }
          }
        }
        if (selectedBall) {
          noFill();
          stroke(255, 215, 0);
          strokeWeight(2);
          ellipse(10 + selectedBall.i * cellSize + cellSize / 2, 10 + selectedBall.j * cellSize + cellSize / 2, cellSize * 0.9);
        }
      }
  
      function drawNextBalls() {
        fill(0);
        textSize(cellSize * 0.3);
        textAlign(LEFT);
        text(&quot;Next:&quot;, 10, gridSize * cellSize + 40);
        for (let k = 0; k &lt; nextBalls.length; k++) {
          drawBall(-1, -1, nextBalls[k], 10 + (k + 1) * cellSize, gridSize * cellSize + 30 + cellSize / 2, 0.5);
        }
      }
  
      function drawScore() {
        fill(0);
        textSize(cellSize * 0.3);
        text(`Score: ${score}`, 10, gridSize * cellSize + 80);
      }
  
      function drawBall(i, j, col, customX = null, customY = null, scale = 1) {
        let x = customX || 10 + i * cellSize + cellSize / 2;
        let y = customY || 10 + j * cellSize + cellSize / 2;
        let gradient = drawingContext.createRadialGradient(x - cellSize * 0.1 * scale, y - cellSize * 0.1 * scale, 0, x, y, cellSize * 0.4 * scale);
        gradient.addColorStop(0, lightenColor(col));
        gradient.addColorStop(1, col);
        drawingContext.fillStyle = gradient;
        noStroke();
        ellipse(x, y, cellSize * 0.8 * scale);
        fill(255, 255, 255, 150);
        ellipse(x - cellSize * 0.2 * scale, y - cellSize * 0.2 * scale, cellSize * 0.2 * scale);
      }
  
      function lightenColor(hex) {
        let r = parseInt(hex.slice(1,3),16);
        let g = parseInt(hex.slice(3,5),16);
        let b = parseInt(hex.slice(5,7),16);
        r = Math.min(255, r + 50);
        g = Math.min(255, g + 50);
        b = Math.min(255, b + 50);
        return `rgb(${r},${g},${b})`;
      }
  
      function touchStarted() {
        if (gameOver) return false;
        let coords = touches.length &gt; 0 ? { x: touches[0].x, y: touches[0].y } : { x: mouseX, y: mouseY };
        console.log(`Touch/Click at: (${coords.x}, ${coords.y})`);
        let mx = coords.x - 10;
        let my = coords.y - 10;
        let i = Math.floor(mx / cellSize);
        let j = Math.floor(my / cellSize);
        console.log(`Grid position: (${i}, ${j})`);
        if (i &lt; 0 || i &gt;= gridSize || j &lt; 0 || j &gt;= gridSize) {
          console.log(&quot;Touch/Click outside grid, deselecting&quot;);
          selectedBall = null;
          return false;
        }
        if (!selectedBall) {
          if (grid[i][j]) {
            selectedBall = { i, j };
            console.log(`Selected ball at: (${i}, ${j})`);
          } else {
            console.log(&quot;No ball at touched position&quot;);
          }
        } else {
          if (grid[i][j]) {
            if (i === selectedBall.i &amp;&amp; j === selectedBall.j) {
              console.log(&quot;Deselected same ball&quot;);
              selectedBall = null;
            } else {
              console.log(`Reselected new ball at: (${i}, ${j})`);
              selectedBall = { i, j };
            }
          } else {
            if (canMove(selectedBall.i, selectedBall.j, i, j)) {
              moveCount++;
              console.log(`Move ${moveCount}: From (${selectedBall.i}, ${selectedBall.j}) to (${i}, ${j})`);
              let startX = 10 + selectedBall.i * cellSize + cellSize / 2;
              let startY = 10 + selectedBall.j * cellSize + cellSize / 2;
              let endX = 10 + i * cellSize + cellSize / 2;
              let endY = 10 + j * cellSize + cellSize / 2;
              animation = { startX, startY, endX, endY, color: grid[selectedBall.i][selectedBall.j], progress: 0 };
              moveBall(selectedBall.i, selectedBall.j, i, j);
              let lines = checkLines();
              if (lines.length === 0) {
                if (!spawnBalls(nextBalls)) {
                  console.log(&quot;No empty cells for spawning balls, ending game&quot;);
                  gameOver = true;
                } else {
                  nextBalls = generateBalls(3);
                  if (isGridFull() || !isAnyMovePossible()) {
                    console.log(&quot;Grid is full or no moves possible, ending game&quot;);
                    gameOver = true;
                  }
                }
              } else {
                removeLines(lines);
              }
              selectedBall = null;
            } else {
              console.log(`Invalid move: No path from (${selectedBall.i}, ${selectedBall.j}) to (${i}, ${j})`);
              selectedBall = null;
            }
          }
        }
        return false; // Prevent default iOS touch behavior
      }
  
      function mousePressed() {
        if (gameOver) return;
        touchStarted(); // Reuse touchStarted for desktop compatibility
      }
  
      function generateBalls(num) {
        return Array(num).fill().map(() =&gt; random(colors));
      }
  
      function spawnBalls(balls) {
        let emptyCells = [];
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (!grid[i][j]) emptyCells.push({ i, j });
          }
        }
        if (emptyCells.length &lt; balls.length) {
          console.log(&quot;Not enough empty cells for spawning&quot;);
          return false;
        }
        for (let n = 0; n &lt; balls.length; n++) {
          let idx = Math.floor(random(emptyCells.length));
          let { i, j } = emptyCells.splice(idx, 1)[0];
          grid[i][j] = balls[n];
        }
        return true;
      }
  
      function canMove(startI, startJ, endI, endJ) {
        if (startI === endI &amp;&amp; startJ === endJ) return false;
        let queue = [{ i: startI, j: startJ }];
        let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
        visited[startI][startJ] = true;
        let maxIterations = gridSize * gridSize;
        let iterations = 0;
  
        while (queue.length &gt; 0) {
          iterations++;
          if (iterations &gt; maxIterations) {
            console.log(&quot;canMove: Max iterations reached&quot;);
            return false;
          }
          let { i, j } = queue.shift();
          if (i === endI &amp;&amp; j === endJ) return true;
  
          let neighbors = [
            { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
            { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
          ];
  
          for (let { ni, nj } of neighbors) {
            if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
              queue.push({ i: ni, j: nj });
              visited[ni][nj] = true;
            }
          }
        }
        return false;
      }
  
      function isAnyMovePossible() {
        for (let si = 0; si &lt; gridSize; si++) {
          for (let sj = 0; sj &lt; gridSize; sj++) {
            if (grid[si][sj]) {
              let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
              let queue = [{ i: si, j: sj }];
              visited[si][sj] = true;
              while (queue.length &gt; 0) {
                let { i, j } = queue.shift();
                let neighbors = [
                  { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
                  { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
                ];
                for (let { ni, nj } of neighbors) {
                  if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
                    return true;
                  }
                }
              }
            }
          }
        }
        return false;
      }
  
      function moveBall(startI, startJ, endI, endJ) {
        grid[endI][endJ] = grid[startI][startJ];
        grid[startI][startJ] = null;
      }
  
      function checkLines() {
        let lines = [];
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (grid[i][j]) {
              let hLine = checkLine(i, j, 0, 1);
              if (hLine.length &gt;= 5) lines.push(hLine);
              let vLine = checkLine(i, j, 1, 0);
              if (vLine.length &gt;= 5) lines.push(vLine);
              let d1Line = checkLine(i, j, 1, -1);
              if (d1Line.length &gt;= 5) lines.push(d1Line);
              let d2Line = checkLine(i, j, 1, 1);
              if (d2Line.length &gt;= 5) lines.push(d2Line);
            }
          }
        }
        let uniqueLines = [];
        let removed = new Set();
        for (let line of lines) {
          let positions = line.map(p =&gt; `${p.i},${p.j}`);
          if (!positions.some(pos =&gt; removed.has(pos))) {
            uniqueLines.push(line);
            positions.forEach(pos =&gt; removed.add(pos));
          }
        }
        return uniqueLines;
      }
  
      function checkLine(startI, startJ, di, dj) {
        let line = [{ i: startI, j: startJ }];
        let color = grid[startI][startJ];
        let i = startI + di;
        let j = startJ + dj;
        let iterations = 0;
        let maxIterations = gridSize;
        while (i &gt;= 0 &amp;&amp; i &lt; gridSize &amp;&amp; j &gt;= 0 &amp;&amp; j &lt; gridSize &amp;&amp; grid[i][j] === color) {
          iterations++;
          if (iterations &gt; maxIterations) {
            console.log(&quot;checkLine: Max iterations reached&quot;);
            break;
          }
          line.push({ i, j });
          i += di;
          j += dj;
        }
        return line;
      }
  
      function removeLines(lines) {
        for (let line of lines) {
          for (let { i, j } of line) {
            grid[i][j] = null;
          }
          score += line.length * 2;
        }
      }
  
      function isGridFull() {
        for (let i = 0; i &lt; gridSize; i++) {
          for (let j = 0; j &lt; gridSize; j++) {
            if (!grid[i][j]) return false;
          }
        }
        return true;
      }
  
      function restartGame() {
        resetGame();
        console.log(&quot;Game restarted via button&quot;);
      }
    &lt;/script&gt;
  &lt;/div&gt;</description>
            </item>
                    <item>
                <title>8 для моб</title>
                <link>http://margo.mozello.shop/blog3/params/post/5137012/8-dlja-mob</link>
                <pubDate>Tue, 23 Sep 2025 09:41:00 +0000</pubDate>
                <description>&lt;title&gt;Lines 98 - iOS Ad Banner Fix&lt;/title&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0&quot;&gt;
  &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js&quot; onerror=&quot;loadBackupP5()&quot;&gt;&lt;/script&gt;
  &lt;script&gt;
    function loadBackupP5() {
      console.log(&quot;Failed to load p5.js from primary CDN, trying backup...&quot;);
      let script = document.createElement(&#039;script&#039;);
      script.src = &#039;https://unpkg.com/p5@1.4.2/lib/p5.min.js&#039;;
      script.onload = () =&gt; console.log(&quot;Backup p5.js loaded&quot;);
      script.onerror = () =&gt; console.log(&quot;Failed to load p5.js&quot;);
      document.head.appendChild(script);
    }
  &lt;/script&gt;
  &lt;style&gt;
    body { margin: 0; padding: 0; background: linear-gradient(to bottom, #e0f7fa, #b3e5fc); font-family: Arial, sans-serif; -webkit-user-select: none; user-select: none; }
    #game-container { max-width: 100%; width: 100%; margin: 0 auto; padding: 5px; background: #fff; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.3); text-align: center; box-sizing: border-box; position: relative; margin-top: 60px; } /* Added margin-top for ad banner */
    canvas { display: block; margin: 0 auto; border-radius: 8px; touch-action: none; cursor: pointer; width: 100%; max-height: calc(100vh - 70px); } /* Adjusted for banner */
    #restart { position: absolute; top: 5px; right: 5px; padding: 6px 12px; background: #0288d1; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 12px; z-index: 10; }
    #restart:hover, #restart:active { background: #0277bd; }
    @media (max-width: 400px) { 
      #game-container { padding: 3px; margin-top: 50px; } /* Smaller margin for smaller screens */
      #restart { padding: 5px 10px; font-size: 10px; }
      canvas { max-width: 100%; max-height: calc(100vh - 60px); }
    }
  &lt;/style&gt;


&lt;div id=&quot;game-container&quot;&gt;
  &lt;button id=&quot;restart&quot; onclick=&quot;restartGame()&quot;&gt;Restart&lt;/button&gt;
  &lt;script&gt;
    let grid;
    let cellSize;
    let gridSize = 9;
    let colors = [&#039;#f44336&#039;, &#039;#2196f3&#039;, &#039;#4caf50&#039;, &#039;#ffeb3b&#039;, &#039;#9c27b0&#039;, &#039;#00bcd4&#039;, &#039;#ff9800&#039;];
    let selectedBall = null;
    let score = 0;
    let gameOver = false;
    let nextBalls = [];
    let animation = null;
    let moveCount = 0;

    function setup() {
      console.log(&quot;p5.js setup started&quot;);
      pixelDensity(2); // Support Retina display on iPhone 7
      let maxWidth = Math.min(window.innerWidth - 10, 320); // Fixed width for iPhone 7
      let maxHeight = Math.min(window.innerHeight - 70, 400); // Reduced height for ad banner
      cellSize = Math.floor(maxWidth / gridSize);
      let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 80); // Reduced extra height
      let canvas = createCanvas(maxWidth, canvasHeight);
      canvas.parent(&#039;game-container&#039;);
      canvas.style(&#039;touch-action&#039;, &#039;none&#039;);
      console.log(`Canvas size: ${maxWidth}x${canvasHeight}, cellSize: ${cellSize}, window.innerHeight: ${window.innerHeight}`);
      resetGame();
      console.log(&quot;p5.js setup completed&quot;);
    }

    function windowResized() {
      let maxWidth = Math.min(window.innerWidth - 10, 320);
      let maxHeight = Math.min(window.innerHeight - 70, 400);
      cellSize = Math.floor(maxWidth / gridSize);
      let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 80);
      resizeCanvas(maxWidth, canvasHeight);
      console.log(`Resized canvas: ${maxWidth}x${canvasHeight}`);
    }

    function resetGame() {
      grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
      nextBalls = generateBalls(3);
      spawnBalls(nextBalls);
      nextBalls = generateBalls(3);
      score = 0;
      gameOver = false;
      animation = null;
      selectedBall = null;
      moveCount = 0;
      console.log(&quot;Game reset&quot;);
    }

    function draw() {
      if (gameOver) {
        background(255);
        drawGrid();
        drawBalls();
        textAlign(CENTER);
        textSize(cellSize * 0.8);
        fill(255, 0, 0);
        text(&quot;Game Over!&quot;, width / 2, height / 2);
        return;
      }

      background(255);
      drawGrid();
      drawBalls();
      drawNextBalls();
      drawScore();

      if (animation) {
        let { startX, startY, endX, endY, color, progress } = animation;
        let x = lerp(startX, endX, progress);
        let y = lerp(startY, endY, progress);
        drawBall(-1, -1, color, x, y);
        animation.progress += 0.05;
        if (animation.progress &gt;= 1) {
          animation = null;
        }
      }
    }

    function drawGrid() {
      fill(240, 240, 240);
      rect(10, 10, gridSize * cellSize, gridSize * cellSize, 5);
      stroke(200);
      strokeWeight(1);
      for (let i = 0; i &lt;= gridSize; i++) {
        line(10 + i * cellSize, 10, 10 + i * cellSize, 10 + gridSize * cellSize);
        line(10, 10 + i * cellSize, 10 + gridSize * cellSize, 10 + i * cellSize);
      }
    }

    function drawBalls() {
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (grid[i][j]) {
            drawBall(i, j, grid[i][j]);
          }
        }
      }
      if (selectedBall) {
        noFill();
        stroke(255, 215, 0);
        strokeWeight(2);
        ellipse(10 + selectedBall.i * cellSize + cellSize / 2, 10 + selectedBall.j * cellSize + cellSize / 2, cellSize * 0.9);
      }
    }

    function drawNextBalls() {
      fill(0);
      textSize(cellSize * 0.25);
      textAlign(LEFT);
      text(&quot;Next:&quot;, 10, gridSize * cellSize + 30);
      for (let k = 0; k &lt; nextBalls.length; k++) {
        drawBall(-1, -1, nextBalls[k], 10 + (k + 1) * cellSize, gridSize * cellSize + 20 + cellSize / 2, 0.4);
      }
    }

    function drawScore() {
      fill(0);
      textSize(cellSize * 0.25);
      text(`Score: ${score}`, 10, gridSize * cellSize + 60);
    }

    function drawBall(i, j, col, customX = null, customY = null, scale = 1) {
      let x = customX || 10 + i * cellSize + cellSize / 2;
      let y = customY || 10 + j * cellSize + cellSize / 2;
      let gradient = drawingContext.createRadialGradient(x - cellSize * 0.1 * scale, y - cellSize * 0.1 * scale, 0, x, y, cellSize * 0.4 * scale);
      gradient.addColorStop(0, lightenColor(col));
      gradient.addColorStop(1, col);
      drawingContext.fillStyle = gradient;
      noStroke();
      ellipse(x, y, cellSize * 0.8 * scale);
      fill(255, 255, 255, 150);
      ellipse(x - cellSize * 0.2 * scale, y - cellSize * 0.2 * scale, cellSize * 0.2 * scale);
    }

    function lightenColor(hex) {
      let r = parseInt(hex.slice(1,3),16);
      let g = parseInt(hex.slice(3,5),16);
      let b = parseInt(hex.slice(5,7),16);
      r = Math.min(255, r + 50);
      g = Math.min(255, g + 50);
      b = Math.min(255, b + 50);
      return `rgb(${r},${g},${b})`;
    }

    function touchStarted() {
      if (gameOver) return false;
      let coords = touches.length &gt; 0 ? { x: touches[0].x, y: touches[0].y } : { x: mouseX, y: mouseY };
      console.log(`Touch/Click at: (${coords.x}, ${coords.y})`);
      let mx = coords.x - 10;
      let my = coords.y - 10;
      let i = Math.floor(mx / cellSize);
      let j = Math.floor(my / cellSize);
      console.log(`Grid position: (${i}, ${j})`);
      if (i &lt; 0 || i &gt;= gridSize || j &lt; 0 || j &gt;= gridSize) {
        console.log(&quot;Touch/Click outside grid, deselecting&quot;);
        selectedBall = null;
        return false;
      }
      if (!selectedBall) {
        if (grid[i][j]) {
          selectedBall = { i, j };
          console.log(`Selected ball at: (${i}, ${j})`);
        } else {
          console.log(&quot;No ball at touched position&quot;);
        }
      } else {
        if (grid[i][j]) {
          if (i === selectedBall.i &amp;&amp; j === selectedBall.j) {
            console.log(&quot;Deselected same ball&quot;);
            selectedBall = null;
          } else {
            console.log(`Reselected new ball at: (${i}, ${j})`);
            selectedBall = { i, j };
          }
        } else {
          if (canMove(selectedBall.i, selectedBall.j, i, j)) {
            moveCount++;
            console.log(`Move ${moveCount}: From (${selectedBall.i}, ${selectedBall.j}) to (${i}, ${j})`);
            let startX = 10 + selectedBall.i * cellSize + cellSize / 2;
            let startY = 10 + selectedBall.j * cellSize + cellSize / 2;
            let endX = 10 + i * cellSize + cellSize / 2;
            let endY = 10 + j * cellSize + cellSize / 2;
            animation = { startX, startY, endX, endY, color: grid[selectedBall.i][selectedBall.j], progress: 0 };
            moveBall(selectedBall.i, selectedBall.j, i, j);
            let lines = checkLines();
            if (lines.length === 0) {
              if (!spawnBalls(nextBalls)) {
                console.log(&quot;No empty cells for spawning balls, ending game&quot;);
                gameOver = true;
              } else {
                nextBalls = generateBalls(3);
                if (isGridFull() || !isAnyMovePossible()) {
                  console.log(&quot;Grid is full or no moves possible, ending game&quot;);
                  gameOver = true;
                }
              }
            } else {
              removeLines(lines);
            }
            selectedBall = null;
          } else {
            console.log(`Invalid move: No path from (${selectedBall.i}, ${selectedBall.j}) to (${i}, ${j})`);
            selectedBall = null;
          }
        }
      }
      return false; // Prevent default iOS touch behavior
    }

    function mousePressed() {
      if (gameOver) return;
      touchStarted(); // Reuse touchStarted for desktop compatibility
    }

    function generateBalls(num) {
      return Array(num).fill().map(() =&gt; random(colors));
    }

    function spawnBalls(balls) {
      let emptyCells = [];
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (!grid[i][j]) emptyCells.push({ i, j });
        }
      }
      if (emptyCells.length &lt; balls.length) {
        console.log(&quot;Not enough empty cells for spawning&quot;);
        return false;
      }
      for (let n = 0; n &lt; balls.length; n++) {
        let idx = Math.floor(random(emptyCells.length));
        let { i, j } = emptyCells.splice(idx, 1)[0];
        grid[i][j] = balls[n];
      }
      return true;
    }

    function canMove(startI, startJ, endI, endJ) {
      if (startI === endI &amp;&amp; startJ === endJ) return false;
      let queue = [{ i: startI, j: startJ }];
      let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
      visited[startI][startJ] = true;
      let maxIterations = gridSize * gridSize;
      let iterations = 0;

      while (queue.length &gt; 0) {
        iterations++;
        if (iterations &gt; maxIterations) {
          console.log(&quot;canMove: Max iterations reached&quot;);
          return false;
        }
        let { i, j } = queue.shift();
        if (i === endI &amp;&amp; j === endJ) return true;

        let neighbors = [
          { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
          { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
        ];

        for (let { ni, nj } of neighbors) {
          if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
            queue.push({ i: ni, j: nj });
            visited[ni][nj] = true;
          }
        }
      }
      return false;
    }

    function isAnyMovePossible() {
      for (let si = 0; si &lt; gridSize; si++) {
        for (let sj = 0; sj &lt; gridSize; sj++) {
          if (grid[si][sj]) {
            let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
            let queue = [{ i: si, j: sj }];
            visited[si][sj] = true;
            while (queue.length &gt; 0) {
              let { i, j } = queue.shift();
              let neighbors = [
                { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
                { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
              ];
              for (let { ni, nj } of neighbors) {
                if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
                  return true;
                }
              }
            }
          }
        }
      }
      return false;
    }

    function moveBall(startI, startJ, endI, endJ) {
      grid[endI][endJ] = grid[startI][startJ];
      grid[startI][startJ] = null;
    }

    function checkLines() {
      let lines = [];
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (grid[i][j]) {
            let hLine = checkLine(i, j, 0, 1);
            if (hLine.length &gt;= 5) lines.push(hLine);
            let vLine = checkLine(i, j, 1, 0);
            if (vLine.length &gt;= 5) lines.push(vLine);
            let d1Line = checkLine(i, j, 1, -1);
            if (d1Line.length &gt;= 5) lines.push(d1Line);
            let d2Line = checkLine(i, j, 1, 1);
            if (d2Line.length &gt;= 5) lines.push(d2Line);
          }
        }
      }
      let uniqueLines = [];
      let removed = new Set();
      for (let line of lines) {
        let positions = line.map(p =&gt; `${p.i},${p.j}`);
        if (!positions.some(pos =&gt; removed.has(pos))) {
          uniqueLines.push(line);
          positions.forEach(pos =&gt; removed.add(pos));
        }
      }
      return uniqueLines;
    }

    function checkLine(startI, startJ, di, dj) {
      let line = [{ i: startI, j: startJ }];
      let color = grid[startI][startJ];
      let i = startI + di;
      let j = startJ + dj;
      let iterations = 0;
      let maxIterations = gridSize;
      while (i &gt;= 0 &amp;&amp; i &lt; gridSize &amp;&amp; j &gt;= 0 &amp;&amp; j &lt; gridSize &amp;&amp; grid[i][j] === color) {
        iterations++;
        if (iterations &gt; maxIterations) {
          console.log(&quot;checkLine: Max iterations reached&quot;);
          break;
        }
        line.push({ i, j });
        i += di;
        j += dj;
      }
      return line;
    }

    function removeLines(lines) {
      for (let line of lines) {
        for (let { i, j } of line) {
          grid[i][j] = null;
        }
        score += line.length * 2;
      }
    }

    function isGridFull() {
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (!grid[i][j]) return false;
        }
      }
      return true;
    }

    function restartGame() {
      resetGame();
      console.log(&quot;Game restarted via button&quot;);
    }
  &lt;/script&gt;
&lt;/div&gt;</description>
            </item>
                    <item>
                <title>7 для моб</title>
                <link>http://margo.mozello.shop/blog3/params/post/5137006/7-dlja-mob</link>
                <pubDate>Tue, 23 Sep 2025 09:30:00 +0000</pubDate>
                <description>&lt;title&gt;Lines 98 - Smaller Field for iOS&lt;/title&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0&quot;&gt;
  &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js&quot; onerror=&quot;loadBackupP5()&quot;&gt;&lt;/script&gt;
  &lt;script&gt;
    function loadBackupP5() {
      console.log(&quot;Failed to load p5.js from primary CDN, trying backup...&quot;);
      let script = document.createElement(&#039;script&#039;);
      script.src = &#039;https://unpkg.com/p5@1.4.2/lib/p5.min.js&#039;;
      script.onload = () =&gt; console.log(&quot;Backup p5.js loaded&quot;);
      script.onerror = () =&gt; console.log(&quot;Failed to load p5.js&quot;);
      document.head.appendChild(script);
    }
  &lt;/script&gt;
  &lt;style&gt;
    body { margin: 0; padding: 0; background: linear-gradient(to bottom, #e0f7fa, #b3e5fc); font-family: Arial, sans-serif; -webkit-user-select: none; user-select: none; }
    #game-container { max-width: 100%; width: 100%; margin: 0 auto; padding: 5px; background: #fff; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.3); text-align: center; box-sizing: border-box; position: relative; }
    canvas { display: block; margin: 0 auto; border-radius: 8px; touch-action: none; cursor: pointer; width: 100%; max-height: 100vh; }
    #restart { position: absolute; top: 5px; right: 5px; padding: 6px 12px; background: #0288d1; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 12px; z-index: 10; }
    #restart:hover, #restart:active { background: #0277bd; }
    @media (max-width: 400px) { 
      #game-container { padding: 3px; } 
      #restart { padding: 5px 10px; font-size: 10px; } 
      canvas { max-width: 100%; max-height: calc(100vh - 10px); }
    }
  &lt;/style&gt;


&lt;div id=&quot;game-container&quot;&gt;
  &lt;button id=&quot;restart&quot; onclick=&quot;restartGame()&quot; fdprocessedid=&quot;d2ifaj&quot;&gt;Restart&lt;/button&gt;
  &lt;script&gt;
    let grid;
    let cellSize;
    let gridSize = 9;
    let colors = [&#039;#f44336&#039;, &#039;#2196f3&#039;, &#039;#4caf50&#039;, &#039;#ffeb3b&#039;, &#039;#9c27b0&#039;, &#039;#00bcd4&#039;, &#039;#ff9800&#039;];
    let selectedBall = null;
    let score = 0;
    let gameOver = false;
    let nextBalls = [];
    let animation = null;
    let moveCount = 0;

    function setup() {
      console.log(&quot;p5.js setup started&quot;);
      pixelDensity(2); // Support Retina display on iPhone 7
      let maxWidth = Math.min(window.innerWidth - 10, 320); // Smaller width for iPhone 7
      let maxHeight = Math.min(window.innerHeight - 10, 480); // Fit iPhone 7 height
      cellSize = Math.floor(maxWidth / gridSize);
      let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 100); // Reduced extra height
      let canvas = createCanvas(maxWidth, canvasHeight);
      canvas.parent(&#039;game-container&#039;);
      canvas.style(&#039;touch-action&#039;, &#039;none&#039;);
      console.log(`Canvas size: ${maxWidth}x${canvasHeight}, cellSize: ${cellSize}`);
      resetGame();
      console.log(&quot;p5.js setup completed&quot;);
    }

    function windowResized() {
      let maxWidth = Math.min(window.innerWidth - 10, 320);
      let maxHeight = Math.min(window.innerHeight - 10, 480);
      cellSize = Math.floor(maxWidth / gridSize);
      let canvasHeight = Math.min(maxHeight, gridSize * cellSize + 100);
      resizeCanvas(maxWidth, canvasHeight);
      console.log(`Resized canvas: ${maxWidth}x${canvasHeight}`);
    }

    function resetGame() {
      grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
      nextBalls = generateBalls(3);
      spawnBalls(nextBalls);
      nextBalls = generateBalls(3);
      score = 0;
      gameOver = false;
      animation = null;
      selectedBall = null;
      moveCount = 0;
      console.log(&quot;Game reset&quot;);
    }

    function draw() {
      if (gameOver) {
        background(255);
        drawGrid();
        drawBalls();
        textAlign(CENTER);
        textSize(cellSize * 0.8);
        fill(255, 0, 0);
        text(&quot;Game Over!&quot;, width / 2, height / 2);
        return;
      }

      background(255);
      drawGrid();
      drawBalls();
      drawNextBalls();
      drawScore();

      if (animation) {
        let { startX, startY, endX, endY, color, progress } = animation;
        let x = lerp(startX, endX, progress);
        let y = lerp(startY, endY, progress);
        drawBall(-1, -1, color, x, y);
        animation.progress += 0.05;
        if (animation.progress &gt;= 1) {
          animation = null;
        }
      }
    }

    function drawGrid() {
      fill(240, 240, 240);
      rect(10, 10, gridSize * cellSize, gridSize * cellSize, 5);
      stroke(200);
      strokeWeight(1);
      for (let i = 0; i &lt;= gridSize; i++) {
        line(10 + i * cellSize, 10, 10 + i * cellSize, 10 + gridSize * cellSize);
        line(10, 10 + i * cellSize, 10 + gridSize * cellSize, 10 + i * cellSize);
      }
    }

    function drawBalls() {
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (grid[i][j]) {
            drawBall(i, j, grid[i][j]);
          }
        }
      }
      if (selectedBall) {
        noFill();
        stroke(255, 215, 0);
        strokeWeight(2);
        ellipse(10 + selectedBall.i * cellSize + cellSize / 2, 10 + selectedBall.j * cellSize + cellSize / 2, cellSize * 0.9);
      }
    }

    function drawNextBalls() {
      fill(0);
      textSize(cellSize * 0.3);
      textAlign(LEFT);
      text(&quot;Next:&quot;, 10, gridSize * cellSize + 40);
      for (let k = 0; k &lt; nextBalls.length; k++) {
        drawBall(-1, -1, nextBalls[k], 10 + (k + 1) * cellSize, gridSize * cellSize + 30 + cellSize / 2, 0.5);
      }
    }

    function drawScore() {
      fill(0);
      textSize(cellSize * 0.3);
      text(`Score: ${score}`, 10, gridSize * cellSize + 80);
    }

    function drawBall(i, j, col, customX = null, customY = null, scale = 1) {
      let x = customX || 10 + i * cellSize + cellSize / 2;
      let y = customY || 10 + j * cellSize + cellSize / 2;
      let gradient = drawingContext.createRadialGradient(x - cellSize * 0.1 * scale, y - cellSize * 0.1 * scale, 0, x, y, cellSize * 0.4 * scale);
      gradient.addColorStop(0, lightenColor(col));
      gradient.addColorStop(1, col);
      drawingContext.fillStyle = gradient;
      noStroke();
      ellipse(x, y, cellSize * 0.8 * scale);
      fill(255, 255, 255, 150);
      ellipse(x - cellSize * 0.2 * scale, y - cellSize * 0.2 * scale, cellSize * 0.2 * scale);
    }

    function lightenColor(hex) {
      let r = parseInt(hex.slice(1,3),16);
      let g = parseInt(hex.slice(3,5),16);
      let b = parseInt(hex.slice(5,7),16);
      r = Math.min(255, r + 50);
      g = Math.min(255, g + 50);
      b = Math.min(255, b + 50);
      return `rgb(${r},${g},${b})`;
    }

    function touchStarted() {
      if (gameOver) return false;
      let coords = touches.length &gt; 0 ? { x: touches[0].x, y: touches[0].y } : { x: mouseX, y: mouseY };
      console.log(`Touch/Click at: (${coords.x}, ${coords.y})`);
      let mx = coords.x - 10;
      let my = coords.y - 10;
      let i = Math.floor(mx / cellSize);
      let j = Math.floor(my / cellSize);
      console.log(`Grid position: (${i}, ${j})`);
      if (i &lt; 0 || i &gt;= gridSize || j &lt; 0 || j &gt;= gridSize) {
        console.log(&quot;Touch/Click outside grid, deselecting&quot;);
        selectedBall = null;
        return false;
      }
      if (!selectedBall) {
        if (grid[i][j]) {
          selectedBall = { i, j };
          console.log(`Selected ball at: (${i}, ${j})`);
        } else {
          console.log(&quot;No ball at touched position&quot;);
        }
      } else {
        if (grid[i][j]) {
          if (i === selectedBall.i &amp;&amp; j === selectedBall.j) {
            console.log(&quot;Deselected same ball&quot;);
            selectedBall = null;
          } else {
            console.log(`Reselected new ball at: (${i}, ${j})`);
            selectedBall = { i, j };
          }
        } else {
          if (canMove(selectedBall.i, selectedBall.j, i, j)) {
            moveCount++;
            console.log(`Move ${moveCount}: From (${selectedBall.i}, ${selectedBall.j}) to (${i}, ${j})`);
            let startX = 10 + selectedBall.i * cellSize + cellSize / 2;
            let startY = 10 + selectedBall.j * cellSize + cellSize / 2;
            let endX = 10 + i * cellSize + cellSize / 2;
            let endY = 10 + j * cellSize + cellSize / 2;
            animation = { startX, startY, endX, endY, color: grid[selectedBall.i][selectedBall.j], progress: 0 };
            moveBall(selectedBall.i, selectedBall.j, i, j);
            let lines = checkLines();
            if (lines.length === 0) {
              if (!spawnBalls(nextBalls)) {
                console.log(&quot;No empty cells for spawning balls, ending game&quot;);
                gameOver = true;
              } else {
                nextBalls = generateBalls(3);
                if (isGridFull() || !isAnyMovePossible()) {
                  console.log(&quot;Grid is full or no moves possible, ending game&quot;);
                  gameOver = true;
                }
              }
            } else {
              removeLines(lines);
            }
            selectedBall = null;
          } else {
            console.log(`Invalid move: No path from (${selectedBall.i}, ${selectedBall.j}) to (${i}, ${j})`);
            selectedBall = null;
          }
        }
      }
      return false; // Prevent default iOS touch behavior
    }

    function mousePressed() {
      if (gameOver) return;
      touchStarted(); // Reuse touchStarted for desktop compatibility
    }

    function generateBalls(num) {
      return Array(num).fill().map(() =&gt; random(colors));
    }

    function spawnBalls(balls) {
      let emptyCells = [];
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (!grid[i][j]) emptyCells.push({ i, j });
        }
      }
      if (emptyCells.length &lt; balls.length) {
        console.log(&quot;Not enough empty cells for spawning&quot;);
        return false;
      }
      for (let n = 0; n &lt; balls.length; n++) {
        let idx = Math.floor(random(emptyCells.length));
        let { i, j } = emptyCells.splice(idx, 1)[0];
        grid[i][j] = balls[n];
      }
      return true;
    }

    function canMove(startI, startJ, endI, endJ) {
      if (startI === endI &amp;&amp; startJ === endJ) return false;
      let queue = [{ i: startI, j: startJ }];
      let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
      visited[startI][startJ] = true;
      let maxIterations = gridSize * gridSize;
      let iterations = 0;

      while (queue.length &gt; 0) {
        iterations++;
        if (iterations &gt; maxIterations) {
          console.log(&quot;canMove: Max iterations reached&quot;);
          return false;
        }
        let { i, j } = queue.shift();
        if (i === endI &amp;&amp; j === endJ) return true;

        let neighbors = [
          { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
          { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
        ];

        for (let { ni, nj } of neighbors) {
          if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
            queue.push({ i: ni, j: nj });
            visited[ni][nj] = true;
          }
        }
      }
      return false;
    }

    function isAnyMovePossible() {
      for (let si = 0; si &lt; gridSize; si++) {
        for (let sj = 0; sj &lt; gridSize; sj++) {
          if (grid[si][sj]) {
            let visited = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(false));
            let queue = [{ i: si, j: sj }];
            visited[si][sj] = true;
            while (queue.length &gt; 0) {
              let { i, j } = queue.shift();
              let neighbors = [
                { ni: i + 1, nj: j }, { ni: i - 1, nj: j },
                { ni: i, nj: j + 1 }, { ni: i, nj: j - 1 }
              ];
              for (let { ni, nj } of neighbors) {
                if (ni &gt;= 0 &amp;&amp; ni &lt; gridSize &amp;&amp; nj &gt;= 0 &amp;&amp; nj &lt; gridSize &amp;&amp; !visited[ni][nj] &amp;&amp; !grid[ni][nj]) {
                  return true;
                }
              }
            }
          }
        }
      }
      return false;
    }

    function moveBall(startI, startJ, endI, endJ) {
      grid[endI][endJ] = grid[startI][startJ];
      grid[startI][startJ] = null;
    }

    function checkLines() {
      let lines = [];
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (grid[i][j]) {
            let hLine = checkLine(i, j, 0, 1);
            if (hLine.length &gt;= 5) lines.push(hLine);
            let vLine = checkLine(i, j, 1, 0);
            if (vLine.length &gt;= 5) lines.push(vLine);
            let d1Line = checkLine(i, j, 1, -1);
            if (d1Line.length &gt;= 5) lines.push(d1Line);
            let d2Line = checkLine(i, j, 1, 1);
            if (d2Line.length &gt;= 5) lines.push(d2Line);
          }
        }
      }
      let uniqueLines = [];
      let removed = new Set();
      for (let line of lines) {
        let positions = line.map(p =&gt; `${p.i},${p.j}`);
        if (!positions.some(pos =&gt; removed.has(pos))) {
          uniqueLines.push(line);
          positions.forEach(pos =&gt; removed.add(pos));
        }
      }
      return uniqueLines;
    }

    function checkLine(startI, startJ, di, dj) {
      let line = [{ i: startI, j: startJ }];
      let color = grid[startI][startJ];
      let i = startI + di;
      let j = startJ + dj;
      let iterations = 0;
      let maxIterations = gridSize;
      while (i &gt;= 0 &amp;&amp; i &lt; gridSize &amp;&amp; j &gt;= 0 &amp;&amp; j &lt; gridSize &amp;&amp; grid[i][j] === color) {
        iterations++;
        if (iterations &gt; maxIterations) {
          console.log(&quot;checkLine: Max iterations reached&quot;);
          break;
        }
        line.push({ i, j });
        i += di;
        j += dj;
      }
      return line;
    }

    function removeLines(lines) {
      for (let line of lines) {
        for (let { i, j } of line) {
          grid[i][j] = null;
        }
        score += line.length * 2;
      }
    }

    function isGridFull() {
      for (let i = 0; i &lt; gridSize; i++) {
        for (let j = 0; j &lt; gridSize; j++) {
          if (!grid[i][j]) return false;
        }
      }
      return true;
    }

    function restartGame() {
      resetGame();
      console.log(&quot;Game restarted via button&quot;);
    }
  &lt;/script&gt;
&lt;/div&gt;</description>
            </item>
            </channel>
</rss>