У Вас отключён javascript.
В данном режиме, отображение ресурса
браузером не поддерживается

02.10 // Активисты сентября Объявлены результаты голосования!

06.09 // Обновление дизайна Дизайн форума обновился к осени! Можно как поставить тёмную версию, так и вернуть оформление любого другого сезона с помощью кнопочки в левом верхнем углу сайта.

активисты месяца
нам нужны
настройки
Шрифт в постах

    Warrior Cats: The Voice of Memories

    Информация о пользователе

    Привет, Гость! Войдите или зарегистрируйтесь.


    Вы здесь » Warrior Cats: The Voice of Memories » Общение » флуд №108 в честь змейки


    флуд №108 в честь змейки

    Сообщений 31 страница 60 из 143

    1

    [hideprofile]

    https://upforme.ru/uploads/001c/55/b9/8/635092.jpg
    Голосуй за нас в топе!https://i.ibb.co/CsHv4TG5/image.png
    (переходи на форум по ссылке топа, чтобы поднять нас выше)

    [html]
    <div id="warriors-hub">
    <style>
    #warriors-hub{--ink:#eee9d9;--muted:#c6cec3;--line:rgba(190,204,169,.32);box-sizing:border-box;width:100%;max-width:900px;margin:0 auto;color:var(--ink);font:14px/1.5 Georgia,"Times New Roman",serif}
    #warriors-hub *{box-sizing:border-box}
    #warriors-hub a{color:inherit;text-decoration:none}
    #warriors-hub a:hover{text-decoration:underline}
    #warriors-hub button,#warriors-hub select{font:inherit}
    #warriors-hub [hidden]{display:none!important}
    #warriors-hub .wh-panel{position:relative;margin:0 0 12px;overflow:hidden;border:1px solid var(--line);border-radius:4px;background:radial-gradient(circle at 12px 12px,rgba(220,225,205,.13) 1px,transparent 1.8px),radial-gradient(circle at 32px 28px,rgba(220,225,205,.1) 1px,transparent 1.8px),linear-gradient(135deg,#172b39,#233d48);background-size:42px 42px,48px 48px,auto;box-shadow:0 2px 7px #0002}
    #warriors-hub .wh-toggle{display:flex;width:100%;min-height:42px;align-items:center;justify-content:space-between;gap:10px;padding:10px 14px;border:0;border-bottom:1px solid var(--line);background:transparent;color:#e6dfc5;text-align:left;text-transform:uppercase;letter-spacing:1.2px;cursor:pointer}
    #warriors-hub .wh-toggle:hover{background:#ffffff0d}
    #warriors-hub .wh-arrow{transition:transform .2s}
    #warriors-hub .wh-toggle[aria-expanded=true] .wh-arrow{transform:rotate(180deg)}
    #warriors-hub .wh-content{padding:12px}
    #warriors-hub .wh-game{padding:14px;overflow:visible}
    #warriors-hub .wh-game-title{margin:0 0 10px 105px;color:#e6dfc5;font-size:19px;font-weight:normal;letter-spacing:2px;text-transform:uppercase}
    #warriors-hub .wh-game-layout{display:grid;grid-template-columns:minmax(100px,.65fr) minmax(0,1.8fr);gap:8px;align-items:center}
    #warriors-hub .wh-cat-side{position:relative;z-index:2;align-self:stretch;display:flex;min-width:0;flex-direction:column;justify-content:center;margin-right:-24px;pointer-events:none}
    #warriors-hub .wh-cat-image{display:block;width:100%;max-width:205px;max-height:235px;margin:0 auto;object-fit:contain;filter:drop-shadow(0 4px 5px #0005)}
    #warriors-hub .wh-cat-placeholder{display:flex;min-height:140px;flex-direction:column;align-items:center;justify-content:center;color:#c5c9b5;font-size:42px;text-align:center}
    #warriors-hub .wh-cat-placeholder small{font-size:11px;letter-spacing:1px}
    #warriors-hub .wh-cat-speech{position:absolute;top:100px;left:50%;z-index:5;width:max-content;max-width:min(230px,75vw);padding:7px 10px;transform:translateX(-50%);border:1px solid #a9b78d;border-radius:8px;background:#091612f2;color:#f0e6c9;font-size:12px;line-height:1.35;text-align:center;box-shadow:0 3px 8px #0005}
    #warriors-hub .wh-cat-speech:after{position:absolute;bottom:-6px;left:50%;width:10px;height:10px;transform:translateX(-50%) rotate(45deg);border-right:1px solid #a9b78d;border-bottom:1px solid #a9b78d;background:#091612;content:""}
    #warriors-hub .wh-board-wrap{position:relative;z-index:1;min-width:0}
    #warriors-hub .wh-board-stage{position:relative;width:100%;overflow:hidden;border:2px solid #71816a;border-radius:4px;background:#172b25}
    #warriors-hub .wh-board{display:block;width:100%;height:auto;aspect-ratio:22/16;touch-action:none}
    #warriors-hub .wh-start-overlay{position:absolute;inset:2px;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:12px;background:#0d1e18e8;text-align:center}
    #warriors-hub .wh-start-title{margin:0;color:#e8dfbd;font-size:19px;font-weight:normal;letter-spacing:1px}
    #warriors-hub .wh-start-text{margin:0;color:#c9d1bd;font-size:12px}
    #warriors-hub .wh-start-button{padding:9px 17px;border:1px solid #a9b78d;border-radius:4px;background:#485f43;color:#fff4d5;cursor:pointer}
    #warriors-hub .wh-start-button:hover{background:#637b55}
    #warriors-hub .wh-controls{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin-top:9px}
    #warriors-hub .wh-controls label{color:#dce2d0;font-size:12px}
    #warriors-hub .wh-controls select,#warriors-hub .wh-btn{min-height:31px;padding:5px 9px;border:1px solid #819078;border-radius:4px;background:#283e39;color:#eee9d9}
    #warriors-hub .wh-btn{cursor:pointer}
    #warriors-hub .wh-btn:hover{background:#526849}
    #warriors-hub .wh-score{margin-left:auto;color:#e0d5a8;white-space:nowrap}
    #warriors-hub .wh-help{margin:8px 0 0;color:#bfc8b8;font-size:11px}
    #warriors-hub .wh-pad{display:grid;grid-template-columns:repeat(3,36px);gap:4px;justify-content:center;margin:9px auto 0}
    #warriors-hub .wh-pad button{width:36px;height:30px;border:1px solid #819078;border-radius:4px;background:#2b433b;color:#f0ead9;cursor:pointer;touch-action:manipulation}
    #warriors-hub .wh-pad .wh-up{grid-column:2}
    #warriors-hub .wh-pad .wh-left{grid-column:1;grid-row:2}
    #warriors-hub .wh-pad .wh-down{grid-column:2;grid-row:2}
    #warriors-hub .wh-pad .wh-right{grid-column:3;grid-row:2}
    #warriors-hub .wh-star-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(125px,.95fr) minmax(0,1fr);gap:9px;align-items:stretch}
    #warriors-hub .wh-cat-card{display:flex;align-items:center;gap:9px;min-width:0;padding:9px;overflow:hidden;border:1px solid #dadcc433;border-radius:4px;background:#0a161f80}
    #warriors-hub .wh-cat-card.wh-right{flex-direction:row-reverse}
    #warriors-hub .wh-avatar{display:block;flex:0 0 68px;width:68px;height:86px;border:1px solid #6e7b6b;border-radius:3px;background:#34463e;object-fit:cover}
    #warriors-hub .wh-cat-info{min-width:0;overflow-wrap:anywhere}
    #warriors-hub .wh-cat-name{display:inline-block;margin-bottom:4px;color:#e8d9a8;font-size:14px;line-height:1.35}
    #warriors-hub .wh-cat-desc{margin:0;color:var(--muted);font-size:12px;line-height:1.5}
    #warriors-hub .wh-bulletins{display:flex;flex-direction:column;justify-content:center;gap:8px;min-width:0;padding:12px;border:1px solid var(--line);border-radius:4px;background:#0510196b}
    #warriors-hub .wh-bulletins a{overflow-wrap:anywhere;color:#e7e1c9}
    #warriors-hub .wh-clan-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
    #warriors-hub .wh-clan-card{display:flex;min-width:0;gap:10px;padding:9px;overflow:hidden;border:1px solid var(--clan);border-radius:4px;background:var(--clan-bg)}
    #warriors-hub .wh-clan-card:last-child:nth-child(odd){grid-column:1/-1;width:calc(50% - 5px);justify-self:center}
    #warriors-hub .wh-storm{--clan:#bd6961;--clan-bg:#682b2ba6}
    #warriors-hub .wh-river{--clan:#65b0c8;--clan-bg:#254e66a6}
    #warriors-hub .wh-wind{--clan:#ad91cc;--clan-bg:#4d3867b3}
    #warriors-hub .wh-shadow{--clan:#8baa75;--clan-bg:#304c2db8}
    #warriors-hub .wh-rogue{--clan:#dfc468;--clan-bg:#655224b8}
    #warriors-hub .wh-clan-link{display:flex;flex:0 0 76px;align-self:stretch;width:76px;min-height:94px;overflow:hidden;border:1px solid #ffffff4d;border-radius:3px;background:#0003}
    #warriors-hub .wh-clan-avatar{display:block;width:100%;height:100%;min-height:94px;object-fit:cover}
    #warriors-hub .wh-clan-copy{min-width:0;align-self:center;overflow-wrap:anywhere}
    #warriors-hub .wh-clan-name{display:block;margin-bottom:4px;color:#fff0cf;font-size:14px;line-height:1.35;letter-spacing:.4px;text-transform:uppercase}
    #warriors-hub .wh-clan-desc{margin:0 0 6px;color:#e0e4d8;font-size:12px;line-height:1.5}
    #warriors-hub .wh-read{color:#fff0c5;font-size:11px;text-decoration:underline}
    #warriors-hub .wh-footer{margin:8px 0 0;color:#aeb9ac;font-size:10px;text-align:center}

    #warriors-hub .wh-game-switcher{margin:0 0 14px}
    #warriors-hub .wh-game-choice[aria-pressed=true]{background:#71835a;color:#fff4d5;border-color:#d1d9ad}
    #warriors-hub .wh-game-screen{padding:12px 0;animation:wh-screen-enter .28s ease-out both}
    #warriors-hub .wh-game{background:radial-gradient(ellipse at 50% 0%,#49604755,transparent 48%),radial-gradient(circle at 15% 95%,#7c633333,transparent 30%),linear-gradient(145deg,#172b39,#1c392f 62%,#233d48)}
    #warriors-hub .wh-game-title:before{content:"✦  ";color:#d5bd72}
    #warriors-hub .wh-game-title:after{content:"  ✦";color:#d5bd72}
    #warriors-hub .wh-game-choice{transition:transform .16s ease,background .16s ease,box-shadow .16s ease}
    #warriors-hub .wh-game-choice:hover{transform:translateY(-2px)}
    #warriors-hub .wh-game-choice[aria-pressed=true]{box-shadow:0 0 0 1px #d5bd72,0 0 14px #b8ca7650}
    #warriors-hub .wh-game-screen>.wh-start-title{color:#ead7a1;text-shadow:0 2px 8px #0008}
    #warriors-hub .wh-game-screen>.wh-start-text{max-width:520px;margin-left:auto;margin-right:auto}
    @keyframes wh-screen-enter{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:translateY(0)}}
    #warriors-hub .wh-game-screen[hidden]{display:none!important}
    #warriors-hub .wh-game-screen>.wh-start-title{text-align:center;margin:0 0 5px}
    #warriors-hub .wh-game-screen>.wh-start-text{text-align:center;margin:0 0 12px}
    #warriors-hub .wh-ttt-board{display:grid;grid-template-columns:repeat(3,minmax(0,100px));gap:7px;justify-content:center;margin:14px auto;max-width:320px}
    #warriors-hub .wh-ttt-cell{aspect-ratio:1;border:1px solid #9aa77c;border-radius:5px;background:radial-gradient(circle at 30% 25%,#4a6548,#203b32 72%);color:#f0e6c9;font-size:34px;cursor:pointer;box-shadow:inset 0 0 0 2px #0c1b1680;transition:transform .16s ease,background .16s ease,box-shadow .16s ease}
    #warriors-hub .wh-ttt-cell:not(:disabled):hover{transform:scale(1.04);background:#536849}
    #warriors-hub .wh-ttt-cell:disabled:not(:empty){text-shadow:0 0 12px #e6d59c66}
    #warriors-hub .wh-ttt-cell:disabled{cursor:default;opacity:.9}
    #warriors-hub .wh-ttt-status{color:#e0d5a8}
    #warriors-hub .wh-2048-top{display:flex;justify-content:center;align-items:center;gap:14px;margin:12px 0}
    #warriors-hub .wh-2048-top>span{padding:7px 12px;border:1px solid #d5bd72;border-radius:4px;background:linear-gradient(145deg,#14261f,#263d2d);color:#fff2bd;font-weight:bold;font-size:15px;text-shadow:0 1px 3px #000b;box-shadow:0 2px 8px #0004}
    #warriors-hub .wh-2048-score{color:#fff7cc;font-size:19px;text-shadow:0 0 8px #f5d86c66}
    #warriors-hub .wh-2048-top .wh-btn{border-color:#e0cf8b;background:linear-gradient(145deg,#596e43,#354b36);color:#fff7d7;font-weight:bold;text-shadow:0 1px 2px #0008}
    #warriors-hub .wh-2048-top .wh-btn:hover{background:linear-gradient(145deg,#778c55,#4b6844)}
    #warriors-hub .wh-2048-board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px;width:min(100%,360px);aspect-ratio:1;margin:0 auto;padding:8px;border:1px solid #71816a;border-radius:7px;background:#172b25;touch-action:none;outline-offset:3px}
    #warriors-hub .wh-2048-cell{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;min-width:0;border:1px solid #b4c39f30;border-radius:5px;background:linear-gradient(145deg,#43584a,#293e34);color:#f4edda;font:bold clamp(17px,4vw,27px) Georgia,serif;box-shadow:inset 0 0 0 1px #07150e70;transition:filter .15s ease}
    #warriors-hub .wh-2048-cell{font-size:clamp(20px,4.8vw,29px);font-weight:700;letter-spacing:.2px;text-shadow:0 1px 2px #0005}
    #warriors-hub .wh-2048-cell small{display:block;margin-top:3px;font:bold 10px/1.15 Georgia,serif;letter-spacing:.45px;text-transform:uppercase;opacity:1;text-shadow:0 1px 1px #0002}
    #warriors-hub .wh-2048-cell[data-value="2"] small,#warriors-hub .wh-2048-cell[data-value="4"] small,#warriors-hub .wh-2048-cell[data-value="8"] small,#warriors-hub .wh-2048-cell[data-value="16"] small,#warriors-hub .wh-2048-cell[data-value="128"] small,#warriors-hub .wh-2048-cell[data-value="256"] small,#warriors-hub .wh-2048-cell[data-value="1024"] small,#warriors-hub .wh-2048-cell[data-value="2048"] small{color:#20291f;text-shadow:none}
    #warriors-hub .wh-2048-cell[data-value="32"] small,#warriors-hub .wh-2048-cell[data-value="64"] small,#warriors-hub .wh-2048-cell[data-value="512"] small{color:#fff;text-shadow:0 1px 2px #0008}
    #warriors-hub .wh-game-screen[data-screen="2048"]>.wh-start-text{color:#f0f3e8;font-size:14px;text-shadow:0 1px 3px #0008}
    #warriors-hub .wh-game-screen[data-screen="2048"] .wh-help{color:#e2eadb;font-size:12px;text-shadow:0 1px 2px #0008}
    #warriors-hub .wh-2048-cell[data-value="2"]{background:linear-gradient(145deg,#e6e4c9,#b7c5a0);color:#24352a;border-color:#e5edc5}
    #warriors-hub .wh-2048-cell[data-value="4"]{background:linear-gradient(145deg,#a9d3a2,#5e9a70);color:#142d20;border-color:#b7e7b3}
    #warriors-hub .wh-2048-cell[data-value="8"]{background:linear-gradient(145deg,#f0cb73,#bd873c);color:#382814;border-color:#f7dc9b}
    #warriors-hub .wh-2048-cell[data-value="16"]{background:linear-gradient(145deg,#e7a16d,#b75d3d);color:#321b14;border-color:#f4b58a}
    #warriors-hub .wh-2048-cell[data-value="32"]{background:linear-gradient(145deg,#d9858d,#a94460);color:#fff4e8;border-color:#f3a9b3}
    #warriors-hub .wh-2048-cell[data-value="64"]{background:linear-gradient(145deg,#c18be0,#8050ae);color:#fff3ff;border-color:#dcb5f2}
    #warriors-hub .wh-2048-cell[data-value="128"]{background:linear-gradient(145deg,#81d4d5,#328b9b);color:#102b35;border-color:#a6f0ed}
    #warriors-hub .wh-2048-cell[data-value="256"]{background:linear-gradient(145deg,#8db6f0,#4d70bd);color:#101e3b;border-color:#b2d2ff}
    #warriors-hub .wh-2048-cell[data-value="512"]{background:linear-gradient(145deg,#e6a9d6,#b85b9e);color:#35142e;border-color:#f6c6e9}
    #warriors-hub .wh-2048-cell[data-value="1024"]{background:linear-gradient(145deg,#f0d97c,#d1a72e);color:#382b0b;border-color:#fff0a5}
    #warriors-hub .wh-2048-cell[data-value="2048"]{background:linear-gradient(145deg,#fff5b5,#e8a72d);color:#38220a;border-color:#fff9d8;box-shadow:0 0 14px #f5d86c99,inset 0 0 0 2px #fff4c5}
    #warriors-hub .wh-2048-cell[data-value="0"]{border-color:#a9b78d12;box-shadow:none}
    #warriors-hub .wh-2048-cell:not([data-value="0"]){background-image:radial-gradient(circle at 15% 15%,#ffffff22,transparent 42%)}

    #warriors-hub .wh-kittens{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
    #warriors-hub .wh-kitten{display:flex;gap:12px;align-items:center;min-width:0;padding:12px;border:1px solid var(--line);border-radius:5px;background:#07151c99}
    #warriors-hub .wh-kitten-face{flex:0 0 60px;width:60px;height:60px;display:grid;place-items:center;border-radius:50%;background:#34463e;font-size:38px}
    #warriors-hub .wh-kitten strong{color:#e8d9a8}
    #warriors-hub .wh-kitten p{margin:4px 0 0;color:#e0e4d8;font-size:12px}
    #warriors-hub .wh-kitten-kind .wh-kitten-face{background:#53694a}

    #warriors-hub .wh-play-area{display:grid;grid-template-columns:minmax(95px,145px) minmax(0,1fr) minmax(95px,145px);gap:10px;align-items:stretch;margin-bottom:12px}
    #warriors-hub .wh-play-area>.wh-game{min-width:0;margin:0}
    #warriors-hub .wh-kitten-side{align-self:stretch;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;min-width:0;padding:12px 8px;border:1px solid var(--line);border-radius:4px;background:linear-gradient(160deg,#0a161fba,#34463e99);text-align:center;overflow-wrap:anywhere}
    #warriors-hub .wh-kitten-side strong{color:#e8d9a8;font-size:14px}
    #warriors-hub .wh-kitten-side p{margin:0;color:#e0e4d8;font-size:12px;line-height:1.45}
    #warriors-hub .wh-kitten-side .wh-kitten-face{display:flex;align-items:center;justify-content:center;width:100%;height:auto;min-height:0;flex:0 0 auto;border:0;border-radius:0;overflow:visible;background:transparent;font-size:0;animation:none}
    #warriors-hub .wh-kitten-image{display:block;width:auto;height:auto;max-width:100%;max-height:230px;object-fit:contain;object-position:center;filter:drop-shadow(0 4px 5px #0005);animation:wh-kitten-bob 2.4s ease-in-out infinite}
    #warriors-hub .wh-kitten-image-fallback{display:none;font-size:34px}
    #warriors-hub .wh-kitten-image.is-missing{display:none}
    #warriors-hub .wh-kitten-image.is-missing+.wh-kitten-image-fallback{display:block}
    #warriors-hub .wh-kitten-right .wh-kitten-image{animation-delay:-1.2s}
    @keyframes wh-kitten-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}
    @keyframes wh-board-bump{0%{transform:scale(.995)}50%{transform:scale(1.006)}100%{transform:scale(1)}}
    @keyframes wh-tile-pop{0%{transform:scale(.72) rotate(-2deg);opacity:.45}70%{transform:scale(1.06);opacity:1}100%{transform:scale(1);opacity:1}}
    @keyframes wh-speaking{0%,100%{box-shadow:0 0 0 1px #d5bd72,0 0 8px #d5bd7250}50%{box-shadow:0 0 0 3px #d5bd72,0 0 22px #d5bd7290}}
    #warriors-hub .wh-kitten-side.is-speaking{border-color:#d5bd72;animation:wh-speaking .8s ease-in-out 3;background:linear-gradient(160deg,#263b29,#5a5734)}
    #warriors-hub .wh-kitten-side.is-speaking p{color:#fff1c4;font-weight:bold}
    #warriors-hub .wh-voice-toggle[aria-pressed="false"]{opacity:.65}
    #warriors-hub .wh-voice-toggle{margin-left:auto}
    @keyframes wh-cell-mark{0%{transform:scale(.65) rotate(-8deg);opacity:.3}100%{transform:scale(1) rotate(0);opacity:1}}
    #warriors-hub .wh-ttt-cell{animation:wh-cell-mark .2s ease-out}
    #warriors-hub .wh-2048-cell{animation:wh-tile-pop .18s ease-out}
    #warriors-hub .wh-2048-cell[data-value="0"]{animation:none}
    @media(prefers-reduced-motion:reduce){#warriors-hub .wh-game-screen,#warriors-hub .wh-ttt-cell,#warriors-hub .wh-2048-cell,#warriors-hub .wh-kitten-side,#warriors-hub .wh-kitten-side .wh-kitten-face{animation:none!important;transition:none!important}}
    @media(max-width:760px){#warriors-hub .wh-play-area{grid-template-columns:1fr 1fr;gap:8px}#warriors-hub .wh-play-area>.wh-game{grid-column:1/-1;grid-row:1}#warriors-hub .wh-kitten-side{min-height:120px}#warriors-hub .wh-kitten-side .wh-kitten-image{max-height:140px;max-width:100%}}

    @media(max-width:600px){#warriors-hub .wh-kittens{grid-template-columns:1fr}#warriors-hub .wh-ttt-board{grid-template-columns:repeat(3,minmax(0,86px))}#warriors-hub .wh-2048-cell{font-size:clamp(18px,5.2vw,25px)}#warriors-hub .wh-2048-cell small{font-size:9px}}

    @media(max-width:600px){
    #warriors-hub .wh-game{padding:10px}
    #warriors-hub .wh-game-title{margin-left:0;font-size:16px;text-align:center}
    #warriors-hub .wh-game-layout{grid-template-columns:78px minmax(0,1fr);gap:5px}
    #warriors-hub .wh-cat-side{margin-right:-17px}
    #warriors-hub .wh-cat-image{max-height:150px}
    #warriors-hub .wh-cat-placeholder{min-height:90px;font-size:30px}
    #warriors-hub .wh-star-grid{grid-template-columns:1fr}
    #warriors-hub .wh-bulletins{order:-1}
    #warriors-hub .wh-cat-card.wh-right{flex-direction:row}
    #warriors-hub .wh-avatar{flex-basis:58px;width:58px;height:65px}
    #warriors-hub .wh-clan-grid{grid-template-columns:1fr}
    #warriors-hub .wh-clan-card:last-child:nth-child(odd){grid-column:auto;width:100%}
    #warriors-hub .wh-clan-link{flex-basis:66px;width:66px;min-height:82px}
    #warriors-hub .wh-clan-avatar{min-height:82px}
    #warriors-hub .wh-score{margin-left:0}
    }
    @media(max-width:380px){
    #warriors-hub .wh-game-layout{grid-template-columns:64px minmax(0,1fr)}
    #warriors-hub .wh-cat-side{margin-right:-12px}
    #warriors-hub .wh-controls select{max-width:100%}
    #warriors-hub .wh-start-title{font-size:16px}
    }
    </style>

    <!-- ИГРЫ И КОТЯТА ПО БОКАМ. Картинки заменяются файлами images/ugolok.png и images/pushinka.png; можно указать свой путь/URL в src у соответствующего img. -->
    <div class="wh-play-area">
      <aside class="wh-kitten-side wh-kitten-left" aria-label="Котёнок Тварёныш">
        <div class="wh-kitten-face"><img class="wh-kitten-image" src="https://free-png.ru/wp-content/uploads/2021/05/free-png.ru-383.png" alt="Тварёныш" onerror="this.classList.add('is-missing')"><span class="wh-kitten-image-fallback" aria-hidden="true">🐈‍⬛</span></div>
        <strong>Тварёныш</strong>
        <p class="wh-kitten-line" data-kitten="grumpy" aria-live="polite">Я прокомментирую партию, когда она закончится.</p>
      </aside>
      <section class="wh-panel wh-game">
      <h2 class="wh-game-title">Испытания лесных племён</h2>
      <div class="wh-controls wh-game-switcher" role="group" aria-label="Выбрать игру">
        <button class="wh-btn wh-game-choice" type="button" data-game="snake" aria-pressed="true">Змейка</button>
        <button class="wh-btn wh-game-choice" type="button" data-game="match" aria-pressed="false">Генератор имён</button>
        <button class="wh-btn wh-game-choice" type="button" data-game="2048" aria-pressed="false">2048</button>
        <button class="wh-btn wh-voice-toggle" type="button" aria-pressed="true" aria-label="Включить или выключить озвучку">🔊 Озвучка: вкл.</button>
      </div>

      <section class="wh-game-screen" data-screen="snake">
        <h3 class="wh-start-title">Охотничья тропа</h3>
        <p class="wh-start-text">Стань ловким охотником: собирай мышей, рыб и птиц для своего племени.</p>
        <div class="wh-board-stage"><canvas class="wh-board" width="440" height="320" tabindex="0" aria-label="Игра Змейка"></canvas>
          <div class="wh-start-overlay"><h3 class="wh-start-title">Охотничьи угодья ждут</h3><p class="wh-start-text">Племя рассчитывает на твою ловкость. Найди добычу и вернись в лагерь!</p><button class="wh-start-button wh-begin" type="button">Начать игру</button></div>
        </div>
        <div class="wh-controls">
          <label>Сложность:
            <select class="wh-difficulty"><option value="220">Ученик</option><option value="160" selected>Воитель</option><option value="110">Глашатай</option><option value="80">Предводитель</option></select>
          </label>
          <button class="wh-btn wh-restart" type="button">Заново</button><button class="wh-btn wh-pause" type="button">Пауза</button>
          <span class="wh-score">Добыча: <b>0</b></span>
        </div>
        <div class="wh-pad"><button class="wh-up" data-dir="up" type="button">▲</button><button class="wh-left" data-dir="left" type="button">◀</button><button class="wh-down" data-dir="down" type="button">▼</button><button class="wh-right" data-dir="right" type="button">▶</button></div>
        <p class="wh-help">Стрелки / WASD · На телефоне — кнопки или свайпы.</p>
      </section>

      <section class="wh-game-screen" data-screen="match" hidden>
        <div id="wc-rare">
          <style>
            #wc-rare{--ink:#eee9d9;--muted:#c6cec3;--line:rgba(190,204,169,.32);box-sizing:border-box;width:100%;max-width:900px;margin:0 auto 12px;color:var(--ink);font:14px/1.5 Georgia,"Times New Roman",serif}
            #wc-rare *{box-sizing:border-box}
            #wc-rare .wc-panel{overflow:hidden;border:1px solid var(--line);border-radius:4px;background:radial-gradient(circle at 12px 12px,rgba(220,225,205,.13) 1px,transparent 1.8px),radial-gradient(circle at 32px 28px,rgba(220,225,205,.1) 1px,transparent 1.8px),linear-gradient(135deg,#172b39,#233d48);background-size:42px 42px,48px 48px,auto;box-shadow:0 2px 7px #0002}
            #wc-rare .wc-toggle{display:flex;width:100%;min-height:42px;align-items:center;justify-content:space-between;gap:10px;padding:10px 14px;border:0;border-bottom:1px solid transparent;background:transparent;color:#e6dfc5;text-align:left;text-transform:uppercase;letter-spacing:1.2px;font:inherit;cursor:pointer}
            #wc-rare .wc-toggle:hover{background:#ffffff0d}#wc-rare .wc-toggle[aria-expanded="true"]{border-bottom-color:var(--line)}
            #wc-rare .wc-arrow{flex-shrink:0;transition:transform .2s}#wc-rare .wc-toggle[aria-expanded="true"] .wc-arrow{transform:rotate(180deg)}
            #wc-rare .wc-content{padding:16px}#wc-rare [hidden]{display:none!important}
            #wc-rare .wc-title{margin:0 0 8px;color:#e6dfc5;font-size:19px;font-weight:normal;text-align:center;letter-spacing:1px}
            #wc-rare .wc-heading{margin:0 0 8px;color:#f3e5b4;font-size:20px;font-weight:normal;text-align:center;letter-spacing:1.4px;text-shadow:0 2px 8px #0008}
            #wc-rare .wc-panel{background:radial-gradient(circle at 12px 12px,rgba(220,225,205,.13) 1px,transparent 1.8px),radial-gradient(circle at 32px 28px,rgba(220,225,205,.1) 1px,transparent 1.8px),linear-gradient(145deg,#172b39,#1c392f 62%,#233d48);background-size:42px 42px,48px 48px,auto;border-color:#9baa7c}
            #wc-rare .wc-subtitle{color:#e0e8d6}
            #wc-rare .wc-btn{border-color:#a9b78d;background:linear-gradient(145deg,#354f3e,#263d35);color:#fff5d8;font-weight:bold;text-shadow:0 1px 2px #0008}
            #wc-rare .wc-btn:hover{background:linear-gradient(145deg,#62784d,#405c40);box-shadow:0 0 0 1px #d5bd72}
            #wc-rare .wc-result-box{background:linear-gradient(145deg,#07151de8,#122820e8);border-color:#a9b78d;box-shadow:inset 0 0 18px #0005}
            #wc-rare .wc-result{color:#fff0b8;font-weight:bold;text-shadow:0 2px 7px #000b}
            #wc-rare .wc-desc{color:#e2e9d7}
            #wc-rare .wc-hint{color:#d2dfc8;font-size:12px}
            #wc-rare .wc-subtitle{margin:0 0 18px;color:var(--muted);text-align:center;font-size:13px}
            #wc-rare .wc-divider{height:1px;margin:14px 0;border:0;background:var(--line)}
            #wc-rare .wc-buttons{display:flex;flex-wrap:wrap;justify-content:center;gap:7px;margin:14px 0}
            #wc-rare .wc-btn{min-height:36px;padding:8px 13px;border:1px solid #819078;border-radius:4px;background:#283e39;color:#eee9d9;font:inherit;cursor:pointer;transition:background .2s}
            #wc-rare .wc-btn:hover{background:#526849}#wc-rare .wc-btn:focus-visible,#wc-rare .wc-toggle:focus-visible{outline:2px solid #e0d5a8;outline-offset:-2px}
            #wc-rare .wc-result-box{min-height:105px;margin-top:14px;padding:18px 12px;border:1px solid var(--line);border-radius:4px;background:#0510196b;text-align:center}
            #wc-rare .wc-result{color:#e8dfbd;font-size:25px;line-height:1.35;overflow-wrap:anywhere}
            #wc-rare .wc-desc{margin-top:9px;color:var(--muted);font-size:13px;font-style:italic}
            #wc-rare .wc-hint{margin:12px 0 0;color:#aeb9ac;font-size:11px;text-align:center}
            @media(max-width:480px){#wc-rare .wc-content{padding:12px}#wc-rare .wc-title{font-size:17px}#wc-rare .wc-btn{flex:1 1 40%}#wc-rare .wc-result{font-size:22px}}
          </style>
          <section class="wc-panel">
            <div class="wc-content" id="wc-rare-content">
              <h3 class="wc-heading">✦ Генератор имён ✦</h3>
              <p class="wc-subtitle">Получи имя, о котором шепчут в легендах!</p><hr class="wc-divider">
              <div class="wc-buttons">
                <button class="wc-btn" data-type="warrior" type="button">Воитель</button><button class="wc-btn" data-type="healer" type="button">Целитель</button><button class="wc-btn" data-type="leader" type="button">Предводитель</button><button class="wc-btn" data-type="apprentice" type="button">Оруженосец</button><button class="wc-btn" data-type="elder" type="button">Старейшина</button>
              </div>
              <div class="wc-result-box" aria-live="polite"><div class="wc-result">Имя ещё не выбрано...</div><div class="wc-desc">Выбери звание, чтобы узнать своё имя.</div></div>
              <p class="wc-hint">70% обычных приставок · 30% редких</p>
            </div>
          </section>
        </div>
      </section>
      <section class="wh-game-screen" data-screen="2048" hidden>
        <h3 class="wh-start-title">Путь к Звёздному племени</h3><p class="wh-start-text">Соединяй одинаковые знаки силы и пройди испытание до 2048.</p>
        <div class="wh-2048-top"><span>Счёт: <b class="wh-2048-score">0</b></span><button class="wh-btn wh-2048-restart" type="button">Новая игра</button></div>
        <div class="wh-2048-board" tabindex="0" aria-label="Поле игры 2048"></div>
        <p class="wh-help">Управление: стрелки или WASD. На телефоне — свайпы. Каждое слияние укрепляет твою связь со Звёздным племенем.</p>
      </section>
    </section>
      <aside class="wh-kitten-side wh-kitten-right" aria-label="Котёнок Хорошик">
        <div class="wh-kitten-face"><img class="wh-kitten-image" src="https://free-png.ru/wp-content/uploads/2021/05/free-png.ru-374.png" alt="Хорошик" onerror="this.classList.add('is-missing')"><span class="wh-kitten-image-fallback" aria-hidden="true">🐈</span></div>
        <strong>Хорошик</strong>
        <p class="wh-kitten-line" data-kitten="kind" aria-live="polite">Я буду болеть за тебя! 💚</p>
      </aside>
    </div>

    <!-- ЗВЁЗДНОЕ ПЛЕМЯ -->
    <section class="wh-panel">
    <button class="wh-toggle" type="button" aria-expanded="false" aria-controls="wh-star-content"><span>✦ Новости Звёздного племени ✦</span><span class="wh-arrow">▼</span></button>
    <div class="wh-content" id="wh-star-content" hidden>
    <div class="wh-star-grid">
    <article class="wh-cat-card" id="wh-looking-card"></article>
    <div class="wh-bulletins">
    <a href="ССЫЛКА_НА_НОВОСТЬ_ЗВЕЗДНОГО_ПЛЕМЕНИ_1">— Новость Звёздного племени 1</a>
    <a href="ССЫЛКА_НА_НОВОСТЬ_ЗВЕЗДНОГО_ПЛЕМЕНИ_2">— Новость Звёздного племени 2</a>
    </div>
    <article class="wh-cat-card wh-right" id="wh-welcome-card"></article>
    </div>
    </div>
    </section>

    <!-- НОВОСТИ ПЛЕМЁН -->
    <section class="wh-panel">
    <button class="wh-toggle" type="button" aria-expanded="false" aria-controls="wh-clan-content"><span>✦ Новости племён ✦</span><span class="wh-arrow">▼</span></button>
    <div class="wh-content" id="wh-clan-content" hidden>
    <div class="wh-clan-grid"></div>
    <p class="wh-footer">При каждой загрузке выбирается случайная новость каждого племени.</p>
    </div>
    </section>

    <script>
    (() => {
    const root=document.getElementById('wc-rare');
    if(!root||root.dataset.ready==='1')return;
    root.dataset.ready='1';
    const prefixesCommon=["Барсуко","Лисье","Мыше","Белко","Выдро","Змее","Мухо","Крепко","Львино","Светло","Серо","Перье","Сово","Еже","Лягушко","Кролико","Олене","Овце","Быко","Цвето","Сухо","Темно","Буро","Красно"];
    const prefixesRare=["Тумано","Рассветно","Эхо","Призрачно","Беззвёздно","Нежно","Храбро","Мятно","Сонно","Тихо","Древне","Вечно","Забыто","Отголоско","Громко","Мило","Буре","Хмельно","Мутно"];
    const suffixes={
      warrior:["коготь","клык","шёрста","хвост","бег","прыг","рык","полос","света","спинка","удар","вихрь","гром","пламя","лёд","камень","шипа","грива","тьма","завр"],
      healer:["лист","корень","роса","шёпот","тень","перо","хвоя","лоза","мох","цвета","бутон","пыльца","сок","гриб","метель","туман","лужица"],
      leader:["звёзд","звёздка","комета","метеор","звезда"],
      apprentice:["лапка","коготок","ушко","носик","хвостик","прыг","шёрстка","глазик","зубка","спинка"],
      elder:["шерст","ус","хвост","взгляд","память","тишь","покой","мудрость","след","отзвук","быль","завр"]
    };
    const descriptions={
      warrior:"Имя этого воина звучит как раскат грома — его боятся враги и уважают соплеменники.",
      healer:"Целитель, чьё имя шепчут травы: он слышит лес даже в полной тишине.",
      leader:"Предводитель, чьё имя становится клятвой для всего племени.",
      apprentice:"Юный оруженосец, полный энергии и вопросов — будущее племени начинается с него.",
      elder:"Старейшина, чьё имя хранит память обо всех прошедших сезонах."
    };
    const randomItem=array=>array[Math.floor(Math.random()*array.length)];
    const result=root.querySelector('.wc-result'),desc=root.querySelector('.wc-desc');
    root.querySelectorAll('[data-type]').forEach(button=>button.addEventListener('click',()=>{
      const type=button.dataset.type,pool=Math.random()<.3?prefixesRare:prefixesCommon;
      result.textContent=randomItem(pool)+randomItem(suffixes[type]);desc.textContent=descriptions[type];
    }));
    })();
    </script>

    <script>
    (() => {
    const root=document.getElementById('warriors-hub');
    if(!root||root.dataset.ready==='1')return;
    root.dataset.ready='1';

    root.querySelectorAll('.wh-toggle').forEach(button=>{
    button.addEventListener('click',()=>{
    const panel=root.querySelector('#'+button.getAttribute('aria-controls'));
    const open=button.getAttribute('aria-expanded')==='true';
    button.setAttribute('aria-expanded',String(!open));
    panel.hidden=open;
    });
    });

    /* КОТЫ ДЛЯ БЛОКОВ «ИЩЕМ» И «ДОБРО ПОЖАЛОВАТЬ» */
      const lookingCats = [
        {
          name:'Рокота',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/739398.png',
          description:'Ищем продолжателя Великого Рода!',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p46191'
        },
        {
          name:'Дымчатого',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/485326.jpg',
          description:'Ищем продолжателя Великого Рода!',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p46191'
        },
        {
          name:'Гремучницу',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/87735.png',
          description:'Ищем продолжательницу Великого Рода!',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p46191'
        },
        {
          name:'Папоротника',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/541825.png',
          description:'Ласка нуждается в любимом-нелюбимом Бывшем.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p75056'
        },
        {
          name:'Золу',
          avatar:'https://upforme.ru/uploads/001c/55/b9/35/256120.jpg',
          description:'Разыскивается хитрая, остроязыкая сестрица Сажи.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p103430'
        },
        {
          name:'Вранокрыла',
          avatar:'https://upforme.ru/uploads/001c/55/b9/35/953522.jpg',
          description:'Сажа нуждается в Брате-Патриоте!',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p103430'
        },
        {
          name:'Чертополоха',
          avatar:'https://upforme.ru/uploads/001c/55/b9/35/953522.jpg',
          description:'Темная лошадка Теней, а также братец Сажи.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p103430'
        },
        {
          name:'Кукушку',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/95059.png',
          description:'Река нуждается в сплетнице!',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p109168'
        },
        {
          name:'Кедра',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/466889.png',
          description:'Кто-то должен расшевелить Небосклона.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p120961'
        },
        {
          name:'Пестрокрыльника',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/373157.png',
          description:'Первая любовь колкой Розочки!',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p125547'
        },
        {
          name:'Синеокую',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/439795.png',
          description:'Мама Птички и Невелички, которую очень ждут дочери.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p129752'
        },
        {
          name:'сиблингов Тмина',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/267643.png',
          description:'Расшевелите Ветер своим подростковым бунтом.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p131161'
        },
        {
          name:'Зяблик',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/731235.png',
          description:'Бывшая подруга Мирта, по которой он скучает.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p132713'
        },
        {
          name:'котят Буревестницы',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/676103.png',
          description:'Речные котят, которым не повезло родиться в шторм.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p133710'
        },
        {
          name:'Мрачницу',
          avatar:'https://upforme.ru/uploads/001c/55/b9/324/432199.png',
          description:'Что случилось с Вьюном? В этом разобраться сможет только его Сестра.',
          url:'https://cwvoice.ru/viewtopic.php?id=122#p134038'
        }
      ];

      const welcomeCats = [
        {
          name:'Птичка',
          avatar:'https://forumavatars.ru/img/avatars/001c/55/b9/384-1792526000.png',
          description:'Сестричка Невелички вступила в игру!',
          url:'https://cwvoice.ru/viewtopic.php?id=1443#p134157'
        },
        {
          name:'Медобока',
          avatar:'https://forumavatars.ru/img/avatars/001c/55/b9/382-1792091358.png',
          description:'Так бы и куснули за ее сладкие бочка!',
          url:'https://cwvoice.ru/viewtopic.php?id=1430#p132794'
        },
        {
          name:'Легколап',
          avatar:'https://forumavatars.ru/img/avatars/001c/55/b9/381-1791988405.png',
          description:'Не унываем, ведь очаровательный сын Тенепляса в игре.',
          url:'https://cwvoice.ru/viewtopic.php?id=1429#p132548'
        },
        {
          name:'Кряква',
          avatar:'https://forumavatars.ru/img/avatars/001c/55/b9/379-1792003035.png',
          description:'Ах какая дама! Всем расступиться, Кряква идет!',
          url:'https://cwvoice.ru/viewtopic.php?id=1421#p131927'
        }
    ];

    function renderRandomCat(id,cats,mode){
    const container=root.querySelector('#'+id);
    const cat=cats[Math.floor(Math.random()*cats.length)];
    const link=document.createElement('a');
    link.href=cat.url;
    const img=document.createElement('img');
    img.className='wh-avatar';img.src=cat.avatar;img.alt=cat.name;
    img.onerror=()=>img.style.visibility='hidden';
    link.appendChild(img);
    const info=document.createElement('div');info.className='wh-cat-info';
    const name=document.createElement('a');name.className='wh-cat-name';name.href=cat.url;
    name.textContent=mode==='looking'?'Ищем: '+cat.name:'Добро пожаловать, '+cat.name+'!';
    const desc=document.createElement('p');desc.className='wh-cat-desc';desc.textContent=cat.description;
    info.append(name,desc);container.replaceChildren(link,info);
    }
    renderRandomCat('wh-looking-card',lookingCats,'looking');
    renderRandomCat('wh-welcome-card',welcomeCats,'welcome');

    /* ИГРЫ И КОТЯТА-КОММЕНТАТОРЫ */
    const screens=[...root.querySelectorAll('.wh-game-screen')];
    const choices=[...root.querySelectorAll('.wh-game-choice')];
    const kittenLines={
    grumpy:root.querySelector('[data-kitten="grumpy"]'),
    kind:root.querySelector('[data-kitten="kind"]')
    };
    const comments={
    grumpy:{
      win:['Повезло-повезло.'],
      lose:['Ну ты и гений навигации. Прям как Речной патруль.',
    'Тебя бы даже мышь обогнала. Пешком.',
    'Патруль окончен. Твои навыки так и не найдены.',
    'Я видел пень с реакцией получше.',
    'В следующий раз поручим добычу табуретке.',
    'Поздравляю: ты проиграл собственному хвосту.',
    'Даже рыба бы так не врезалась.',
    'Лапы есть, а координация где-то потерялась.',
    'План был гениален. Жаль, продержался полсекунды.',
    'Это был не патруль, а экскурсия в ограду.',
    'Звёздное племя просило передать: ну камон.',
    'Удача отвернулась. Навыки тоже.',
    'Ты управлял змейкой или чихал на клавиатуру?',
    'Я бы помог, но мне слишком смешно.',
    'Кажется, мышь только что поставила тебе двойку.',
    'Тактика впечатляет. Особенно её отсутствие.',
    'С таким патрулём даже кусты чувствуют себя в безопасности.',
    'Не переживай: хуже уже не будет. Наверное.']
    },
    kind:{
      win:['Ура! Ты справился! Я так рада! 🌟','Это было замечательно! Ты молодец!','Победа! Отправляю тебе виртуальные обнимашки 💚'],
      lose:['Ничего страшного — каждая попытка учит новому 💚','Не расстраивайся, у тебя обязательно получится!','Ты здорово постарался. Давай попробуем ещё раз!']
    }
    };
    function randomItem(items){return items[Math.floor(Math.random()*items.length)]}
    /* Важно: котята не говорят при старте, ходе, победе или смене игры — только после проигрыша. */
    function commentBoth(kind){ /* Обычные ходы не перебивают итоговые реплики котят. */ }
    let voiceEnabled=true;
    const voiceToggle=root.querySelector('.wh-voice-toggle');
    const kittenSides={grumpy:root.querySelector('.wh-kitten-left'),kind:root.querySelector('.wh-kitten-right')};
    const kittenDefaults={grumpy:'Я прокомментирую партию, когда она закончится.',kind:'Я буду болеть за тебя! 💚'};
    voiceToggle.addEventListener('click',()=>{
    voiceEnabled=!voiceEnabled;
    voiceToggle.setAttribute('aria-pressed',String(voiceEnabled));
    voiceToggle.textContent=voiceEnabled?'🔊 Озвучка: вкл.':'🔇 Озвучка: выкл.';
    if(!voiceEnabled&&'speechSynthesis' in window)window.speechSynthesis.cancel();
    });
    function commentAfterResult(result){
    const who=Math.random()<.5?'grumpy':'kind';
    const phrase=randomItem(comments[who][result]);
    Object.keys(kittenLines).forEach(key=>{
      kittenLines[key].textContent=key===who?phrase:kittenDefaults[key];
      kittenSides[key].classList.toggle('is-speaking',key===who);
    });
    if(voiceEnabled&&'speechSynthesis' in window&&'SpeechSynthesisUtterance' in window){
      try{
       window.speechSynthesis.cancel();
       const utterance=new SpeechSynthesisUtterance(phrase);
       utterance.lang='ru-RU';utterance.rate=who==='kind'?0.9:1.02;utterance.pitch=who==='kind'?1.4:0.78;
       const voices=window.speechSynthesis.getVoices();
       const russianVoice=voices.find(v=>/^ru(-|$)/i.test(v.lang));
       if(russianVoice)utterance.voice=russianVoice;
       window.speechSynthesis.speak(utterance);
      }catch(error){/* Реплика остаётся на экране, если озвучка недоступна. */}
    }
    }
    function selectGame(name){
    screens.forEach(s=>s.hidden=s.dataset.screen!==name);
    choices.forEach(b=>b.setAttribute('aria-pressed',String(b.dataset.game===name)));
    stopSnake();
    commentBoth('start');
    }
    choices.forEach(b=>b.addEventListener('click',()=>selectGame(b.dataset.game)));

    /* ЗМЕЙКА */
    const canvas=root.querySelector('.wh-board'),ctx=canvas.getContext('2d');
    const overlay=root.querySelector('.wh-start-overlay');
    const difficulty=root.querySelector('.wh-difficulty');
    const scoreNode=root.querySelector('.wh-score b');
    const pauseButton=root.querySelector('.wh-pause');
    const cols=22,rows=16,cell=20;
    const colors=['#b7a27d','#7b9b8b','#b47d69','#9b91b5','#d0b85f','#7d9fb2','#bd9baf','#8d9a67'];
    let snake=[],dir={x:1,y:0},next={x:1,y:0},prey=null,score=0,timer=null;
    let running=false,paused=false,over=false,touch=null;
    function stopSnake(){if(timer!==null)clearInterval(timer);timer=null}
    function runTimer(){stopSnake();if(running&&!paused&&!over&&!root.querySelector('[data-screen="snake"]').hidden)timer=setInterval(stepSnake,+difficulty.value)}
    function randomPrey(){
    const occupied=new Set(snake.map(p=>p.x+','+p.y)),free=[];
    for(let y=0;y<rows;y++)for(let x=0;x<cols;x++)if(!occupied.has(x+','+y))free.push({x,y});
    if(!free.length)return null;
    return {...free[Math.floor(Math.random()*free.length)],type:['mouse','fish','bird'][Math.floor(Math.random()*3)]};
    }
    function resetSnake(){
    stopSnake();snake=[{x:10,y:8},{x:9,y:8},{x:8,y:8},{x:7,y:8},{x:6,y:8}];
    dir={x:1,y:0};next={x:1,y:0};score=0;running=true;paused=false;over=false;
    prey=randomPrey();scoreNode.textContent='0';pauseButton.textContent='Пауза';overlay.hidden=true;
    drawSnake();runTimer();canvas.focus();commentBoth('start');
    }
    function setDir(name){
    if(!running||paused||over)return;
    const dirs={up:{x:0,y:-1},down:{x:0,y:1},left:{x:-1,y:0},right:{x:1,y:0}};
    const d=dirs[name];if(!d||(d.x===-next.x&&d.y===-next.y))return;next=d;
    }
    function stepSnake(){
    if(!running||paused||over||root.querySelector('[data-screen="snake"]').hidden)return;
    dir=next;const head={x:snake[0].x+dir.x,y:snake[0].y+dir.y};
    if(head.x<0||head.x>=cols||head.y<0||head.y>=rows){endSnake('Патруль заблудился!');return}
    const eating=prey&&head.x===prey.x&&head.y===prey.y;
    const body=eating?snake:snake.slice(0,-1);
    if(body.some(p=>p.x===head.x&&p.y===head.y)){endSnake('Патруль столкнулся!');return}
    snake.unshift(head);
    if(eating){score++;scoreNode.textContent=score;prey=randomPrey();commentBoth('move');if(!prey){over=true;running=false;stopSnake();drawSnake();commentAfterResult('win');return}}
    else snake.pop();
    drawSnake();
    }
    function drawSnakeCat(x,y,color,face){
    const px=x*cell,py=y*cell;ctx.save();ctx.fillStyle=color;ctx.strokeStyle='#17251e';ctx.lineWidth=1.5;
    if(face){ctx.beginPath();ctx.moveTo(px+3,py+8);ctx.lineTo(px+3,py+1);ctx.lineTo(px+9,py+5);ctx.lineTo(px+15,py+1);ctx.lineTo(px+17,py+8);ctx.quadraticCurveTo(px+20,py+15,px+10,py+18);ctx.quadraticCurveTo(px,py+16,px+3,py+8);ctx.closePath();ctx.fill();ctx.stroke();ctx.fillStyle='#e7d99b';ctx.beginPath();ctx.arc(px+7,py+10,1.7,0,Math.PI*2);ctx.arc(px+13,py+10,1.7,0,Math.PI*2);ctx.fill()}
    else{ctx.beginPath();ctx.roundRect(px+2,py+2,16,16,4);ctx.fill();ctx.stroke()}ctx.restore();
    }
    function drawPrey(){if(!prey)return;const x=prey.x*cell+10,y=prey.y*cell+10;ctx.save();ctx.translate(x,y);ctx.lineWidth=1;ctx.strokeStyle='#ead9ad';ctx.fillStyle=prey.type==='fish'?'#83b5b6':prey.type==='bird'?'#d8c16e':'#c7a879';ctx.beginPath();ctx.ellipse(0,0,6,4,0,0,Math.PI*2);ctx.fill();ctx.stroke();if(prey.type==='bird'){ctx.beginPath();ctx.moveTo(-5,0);ctx.lineTo(-9,-4);ctx.lineTo(-8,3);ctx.fill()}else if(prey.type==='fish'){ctx.beginPath();ctx.moveTo(5,0);ctx.lineTo(9,-4);ctx.lineTo(9,4);ctx.closePath();ctx.fill()}else{ctx.beginPath();ctx.arc(-5,-4,2.2,0,Math.PI*2);ctx.arc(0,-5,2.2,0,Math.PI*2);ctx.fill()}ctx.restore()}
    function snakeMessage(text){ctx.save();ctx.fillStyle='#091612e8';ctx.fillRect(20,126,400,68);ctx.strokeStyle='#9aab82';ctx.strokeRect(20,126,400,68);ctx.fillStyle='#f0e6c9';ctx.textAlign='center';ctx.font='bold 16px Georgia';ctx.fillText(text,220,155,380);ctx.font='12px Georgia';ctx.fillText('Нажми «Заново», чтобы снова выйти на охоту',220,177);ctx.restore()}
    function drawSnake(){ctx.clearRect(0,0,440,320);ctx.fillStyle='#172b25';ctx.fillRect(0,0,440,320);ctx.strokeStyle='#b4c39f17';ctx.lineWidth=.5;for(let x=0;x<=440;x+=cell){ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,320);ctx.stroke()}for(let y=0;y<=320;y+=cell){ctx.beginPath();ctx.moveTo(0,y);ctx.lineTo(440,y);ctx.stroke()}drawPrey();snake.forEach((p,i)=>drawSnakeCat(p.x,p.y,colors[Math.floor(i/3)%colors.length],i%3===0));if(paused)snakeMessage('Патруль отдыхает')}
    function endSnake(text){over=true;running=false;stopSnake();drawSnake();snakeMessage(text);commentAfterResult('lose')}
    root.querySelector('.wh-begin').addEventListener('click',resetSnake);
    root.querySelector('.wh-restart').addEventListener('click',resetSnake);
    pauseButton.addEventListener('click',()=>{if(!running||over)return;paused=!paused;pauseButton.textContent=paused?'Продолжить':'Пауза';if(paused)stopSnake();else runTimer();drawSnake()});
    difficulty.addEventListener('change',runTimer);
    root.querySelectorAll('[data-dir]').forEach(b=>b.addEventListener('click',()=>setDir(b.dataset.dir)));
    canvas.addEventListener('touchstart',e=>{const t=e.changedTouches[0];touch={x:t.clientX,y:t.clientY}},{passive:true});
    canvas.addEventListener('touchend',e=>{if(!touch)return;const t=e.changedTouches[0],dx=t.clientX-touch.x,dy=t.clientY-touch.y;touch=null;if(Math.max(Math.abs(dx),Math.abs(dy))<18)return;setDir(Math.abs(dx)>Math.abs(dy)?(dx>0?'right':'left'):(dy>0?'down':'up'))},{passive:true});

    /* 2048 */
    const board2048=root.querySelector('.wh-2048-board'),score2048=root.querySelector('.wh-2048-score');
    let grid2048=[],scoreVal=0,done2048=false,touch2048=null;
    function addTile2048(){const empty=[];grid2048.forEach((v,i)=>{if(!v)empty.push(i)});if(empty.length){const i=randomItem(empty);grid2048[i]=Math.random()<.9?2:4}}
    function reset2048(){grid2048=Array(16).fill(0);scoreVal=0;done2048=false;addTile2048();addTile2048();render2048();commentBoth('start')}
    function render2048(){board2048.replaceChildren();const ranks={2:'ученик',4:'оруженосец',8:'воитель',16:'глашатай',32:'старейшина',64:'целитель',128:'предводитель',256:'легенда',512:'избранный',1024:'звезда',2048:'Звёздный'};grid2048.forEach(v=>{const cellEl=document.createElement('div');cellEl.className='wh-2048-cell';cellEl.dataset.value=String(v);cellEl.setAttribute('aria-label',v?ranks[v]+' — '+v:'пустая поляна');if(v){const number=document.createElement('span');number.textContent=String(v);const rank=document.createElement('small');rank.textContent=ranks[v]||'сила';cellEl.append(number,rank)}board2048.appendChild(cellEl)});score2048.textContent=scoreVal}
    function slide2048(line){const vals=line.filter(Boolean);let out=[],gained=0;for(let i=0;i<vals.length;i++){if(vals[i]===vals[i+1]){out.push(vals[i]*2);gained+=vals[i]*2;i++}else out.push(vals[i])}while(out.length<4)out.push(0);return {line:out,gained}}
    function move2048(direction){
    if(done2048||root.querySelector('[data-screen="2048"]').hidden)return;
    const before=grid2048.join(','),nextGrid=Array(16).fill(0);let gained=0;
    for(let n=0;n<4;n++){let ids=[];for(let k=0;k<4;k++){if(direction==='left')ids.push(n*4+k);if(direction==='right')ids.push(n*4+3-k);if(direction==='up')ids.push(k*4+n);if(direction==='down')ids.push((3-k)*4+n)}
      const result=slide2048(ids.map(i=>grid2048[i]));gained+=result.gained;ids.forEach((id,j)=>nextGrid[id]=result.line[j])}
    if(before===nextGrid.join(','))return;grid2048=nextGrid;scoreVal+=gained;
    addTile2048();render2048();commentBoth('move');
    if(grid2048.includes(2048)){done2048=true;commentAfterResult('win');return}
    const canMove=grid2048.some(v=>!v)||grid2048.some((v,i)=>i%4<3&&v===grid2048[i+1])||grid2048.some((v,i)=>i<12&&v===grid2048[i+4]);
    if(!canMove){done2048=true;commentAfterResult('lose')}
    }
    root.querySelector('.wh-2048-restart').addEventListener('click',reset2048);
    function handleGameKey(e){const map={ArrowUp:'up',w:'up',ArrowDown:'down',s:'down',ArrowLeft:'left',a:'left',ArrowRight:'right',d:'right'};if(!map[e.key])return;const active=root.querySelector('.wh-game-screen:not([hidden])');if(!active)return;if(active.dataset.screen==='snake'){e.preventDefault();setDir(map[e.key])}else if(active.dataset.screen==='2048'){e.preventDefault();move2048(map[e.key])}}
    root.addEventListener('keydown',handleGameKey);
    board2048.addEventListener('touchstart',e=>{const t=e.changedTouches[0];touch2048={x:t.clientX,y:t.clientY}},{passive:true});
    board2048.addEventListener('touchend',e=>{if(!touch2048)return;const t=e.changedTouches[0],dx=t.clientX-touch2048.x,dy=t.clientY-touch2048.y;touch2048=null;if(Math.max(Math.abs(dx),Math.abs(dy))<18)return;move2048(Math.abs(dx)>Math.abs(dy)?(dx>0?'right':'left'):(dy>0?'down':'up'))},{passive:true});
    snake=[{x:10,y:8},{x:9,y:8},{x:8,y:8},{x:7,y:8},{x:6,y:8}];prey=randomPrey();drawSnake();reset2048();

    /* НОВОСТИ: У КАЖДОЙ НОВОСТИ СОБСТВЕННЫЙ КОТ, АВАТАРКА И ССЫЛКА.
       При выборе новости все три значения меняются вместе. */
    const clanNews=[
    {
    clan:'storm',name:'Гроза',
    items:[
    {title:'Знакомьтесь, дядя',desc:'Беркут представляет своим детям дядю Огнелапа. Дети представляют Огнелапу законы детской.',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/130-1788777781.png',url:'https://cwvoice.ru/viewtopic.php?id=223#p132700'},
    {title:'Пу-пу... Паутина',desc:'Коты-пауки собирают важный ресурс - паутину!',cat:'https://upforme.ru/uploads/001c/55/b9/324/320955.jpg',url:'https://cwvoice.ru/viewtopic.php?id=220&p=2#p131602'},
    {title:'Если Невеличка молчит...',desc:'Каждый дурак знает, что если Невеличка молчит - ее лучше не перебивать. Поэтому Ежонок тоже молчит.',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/370-1790367075.png',url:'https://cwvoice.ru/viewtopic.php?id=231&p=15#p132674'}
    ]},
    {
    clan:'river',name:'Река',
    items:[
    {title:'Мы где?',desc:'Мирт и Лебедь заблудились, но зато решили поболтать. А Жаба молодец!.',cat:'https://upforme.ru/uploads/001c/55/b9/324/400200.png',url:'https://cwvoice.ru/viewtopic.php?id=265&p=2#p132699'},
    {title:'Как достать глашатая',desc:'ВНИМАНИЕ! Рыбник проводик краш-тест Лазоревки, взорвется ли глашатай? Кто знает...',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/365-1788727545.png',url:'https://cwvoice.ru/viewtopic.php?id=262#p133332'},
    {title:'Ой, мамочки...',desc:'Кряква выгуливает молодежь по границе с Ветром.',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/379-1792003035.png',url:'https://cwvoice.ru/viewtopic.php?id=187&p=2#p134084'},
    {title:'Все, на что падает свет...',desc:'Вьюн показывает земли Речного племени своей ученице.',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/373-1790518978.png',url:'https://cwvoice.ru/viewtopic.php?id=268&p=2#p133201'}
    ]},
    {
    clan:'wind',name:'Ветер',
    items:[
    {title:'Да не умер он!',desc:'Да не умер Терзающий Звезды в конце туннеля!',cat:'https://i.ibb.co/5xWsksxB/19-1788726283.png',url:'https://cwvoice.ru/viewtopic.php?id=159&p=2#p133492'},
    {title:'Сестры бранятся',desc:'Розочка поругалась на Цветолапа, но что-то пошло не так... Зато папа рядом.',cat:'https://upforme.ru/uploads/001c/55/b9/326/583104.png',url:'https://cwvoice.ru/viewtopic.php?id=208&p=15#p134188'},
    {title:'Чей муж?',desc:'Кто мужика обронил? Ну ладно, забираем.',cat:'https://i.ibb.co/wZxLy6yv/1.png',url:'https://cwvoice.ru/viewtopic.php?id=1375#p134099'}
    ]},
    {
    clan:'shadow',name:'Тени',
    items:[
    {title:'Охоту видишь?',desc:'А она есть. Иначе Визг врушка-врушка.',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/274-1775129989.jpg',url:'https://cwvoice.ru/viewtopic.php?id=240#p133658'},
    {title:'Да прогоните его уже',desc:'Барсук пришел, барсук... пока еще не ушел. Но с такими бравыми воителями - скоро!',cat:'https://upforme.ru/uploads/001c/55/b9/9/40719.png',url:'https://cwvoice.ru/viewtopic.php?id=254&p=14#p132030'},
    {title:'я еще не придумал',desc:'простите. спать хчоу.',cat:'ССЫЛКА_НА_КОТА_ТЕНЕЙ_3',url:'ССЫЛКА_НА_НОВОСТЬ_ТЕНЕЙ_3'}
    ]},
    {
    clan:'rogue',name:'Бродяги',
    items:[
    {title:'Ну Рохля, берегись!',desc:'Легендарная встреча Сорняка и Рохли.',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/329-1780748166.png',url:'https://cwvoice.ru/viewtopic.php?id=172#p132444'},
    {title:'Подглядушки...',desc:'Встречаются как-то Волдырь и Бурелом в баре и смотрят...',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/333-1782116775.jpg',url:'https://cwvoice.ru/viewtopic.php?id=166#p130680'},
    {title:'Старость не радость',desc:'Или не теряй башмачки, или прикрывай тылы.',cat:'https://forumavatars.ru/img/avatars/001c/55/b9/248-1788767336.png',url:'https://cwvoice.ru/viewtopic.php?id=181#p123009'}
    ]}
    ];

    const grid=root.querySelector('.wh-clan-grid');
    clanNews.forEach(clan=>{
    const item=clan.items[Math.floor(Math.random()*clan.items.length)];
    const card=document.createElement('article');card.className='wh-clan-card wh-'+clan.clan;

    /* Изображение обёрнуто ссылкой ИМЕННО выбранной новости */
    const imageLink=document.createElement('a');
    imageLink.className='wh-clan-link';imageLink.href=item.url;
    imageLink.setAttribute('aria-label','Открыть новость: '+item.title);
    const img=document.createElement('img');img.className='wh-clan-avatar';
    img.src=item.cat;img.alt='Кот: '+item.title;
    img.onerror=()=>{img.style.visibility='hidden'};
    imageLink.appendChild(img);

    const copy=document.createElement('div');copy.className='wh-clan-copy';
    const title=document.createElement('a');title.className='wh-clan-name';
    title.href=item.url;title.textContent=clan.name+' · '+item.title;
    const desc=document.createElement('p');desc.className='wh-clan-desc';desc.textContent=item.desc;
    const link=document.createElement('a');link.className='wh-read';link.href=item.url;link.textContent='Читать новость →';
    copy.append(title,desc,link);card.append(imageLink,copy);grid.appendChild(card);
    });
    })();
    </script>
    </div>
    [/html]

    Отредактировано Ежонок (Сегодня 12:11:35)

    +9

    31

    https://upforme.ru/uploads/001c/55/b9/18/t753786.png
    я провалилась тк не поняла, что край поля тоже ловушка... ОЧ КРУТО!

    +4

    32

    я новости позже добавлю!!

    +2

    33

    Ежонок, ты молодец!!

    +1

    34

    Надо сегодня посты пописать, если силами соберусь

    0

    35

    Невеличка, почти готово! Сейчас скину, скажешь как оно

    +1

    36

    Птичка, хорошо

    0

    37

    Птичка, классная анкета!!

    +1

    38

    Птичка, УРААА с принятием!!

    +1

    39

    Птичка, с принятием!

    +1

    40

    Как быстро :000
    Спасибо всем!

    +7

    41

    Птичка, добро пожаловать на ролевую!

    +4

    42

    Терзающий Звёзды, добро пожаловать на ролевую!

    +2

    43

    Ежонок, добро пожаловать на ролевую!

    +3

    44

    Вьюн, добро пожаловать на ролевую!

    +3

    45

    Ежонок, не против, если Птичка присоединиться к нам на поляне?

    0

    46

    Невеличка, не против!!

    +2

    47

    Птичка написал(а):

    https://upforme.ru/uploads/001c/55/b9/18/t739218.png

    что за пупс в подписи!

    +4

    48

    Невеличка написал(а):

    Ежонок, не против, если Птичка присоединиться к нам на поляне?

    Я к вам дедом выползу тоже

    +1

    49

    ТОВАРИЩИ СОЦ ОПРОС НА НОЧЬ ГЛЯДЯ
    я ща делаю новости и думаю как все нормально уместить
    так вот, вопрос следующий - змейку оставить в этом флуде? я ее ваще по приколу вставил но хз... вдруг вам прикольно лол

    0

    50

    ахуееееть это что за вайбкодинг игры на войсе!! жесть мне кажется она достойна отдельной темки!!!!!

    +3

    51

    Ежонок, оставлять!

    +1

    52

    Ежонок, очень нравится игра, предлагаю оставить! Она не занимает много места
    Но можешь реально сделать темку куда будешь кидать игры!

    +1

    53

    Ежонок написал(а):

    так вот, вопрос следующий — змейку оставить в этом флуде? я ее ваще по приколу вставил но хз... вдруг вам прикольно лол

    оставь!!! я тоже уже вайбкожу игру ахахахах
    такого наверн ни на одном форуме нет)) впору прям игровую тему где то создать со складом наших игр и авторством конкретных людей)

    +6

    54

    Ежонок написал(а):

    ТОВАРИЩИ СОЦ ОПРОС НА НОЧЬ ГЛЯДЯ
    я ща делаю новости и думаю как все нормально уместить
    так вот, вопрос следующий — змейку оставить в этом флуде? я ее ваще по приколу вставил но хз... вдруг вам прикольно лол

    оставляем конеш! офигенная штука, спасибо за идею!

    +1

    55

    потестируем еще одну игрульку?? это бета версия, навайбкоженная человеком, который впервые чет вайбкодил........

    [html]
    <style>
    #herb-forum{
      --bg:#101d19;
      --panel:#20372b;
      --panel-2:#2b4736;
      --cream:#f8ebcf;
      --mint:#a6d99a;
      --gold:#e9c77e;
      --line:#5d7454;
    }
    #herb-forum *{box-sizing:border-box}
    #herb-forum{font-family:system-ui,-apple-system,Segoe UI,sans-serif;color:#f8ebcf;
     
     
     
     
     
      font-family:system-ui,-apple-system,Segoe UI,sans-serif;
      color:var(--cream);
     
    }
    #herb-forum .game{
      width:min(100%,640px);
      background:linear-gradient(180deg,#22382d 0%,#17271f 100%);
      border:1px solid var(--line);
      border-radius:28px;
      padding:clamp(13px,3vw,24px);
      box-shadow:0 24px 80px #0007;
    }
    #herb-forum header{text-align:center}
    #herb-forum h1{
      font-family:Georgia,serif;
      margin:0;
      font-size:clamp(29px,6vw,39px);
      font-weight:500;
      color:#f6dfab;
      letter-spacing:.02em;
    }
    #herb-forum header p{
      margin:7px 0 16px;
      color:#b3cbb4;
      font-size:14px;
    }
    #herb-forum .stats{
      display:grid;
      grid-template-columns:repeat(3,1fr);
      gap:8px;
      margin-bottom:14px;
    }
    #herb-forum .stat{
      background:linear-gradient(180deg,#314f3d,#294436);
      border:1px solid #49634c;
      border-radius:13px;
      padding:9px;
      text-align:center;
    }
    #herb-forum .stat small{
      display:block;
      font-size:11px;
      text-transform:uppercase;
      letter-spacing:.11em;
      color:#bad2bd;
    }
    #herb-forum .stat b{font-size:24px;color:#fff0c7}
    #herb-forum .goal{text-align:center;margin:0 0 12px;color:#cbdabc;font-size:13px}
    #herb-forum .board{
      display:grid;
      grid-template-columns:repeat(8,1fr);
      gap:5px;
      background:
        linear-gradient(180deg,#38553f,#314c38);
      border:7px solid #395741;
      border-radius:20px;
      padding:2px;
      touch-action:pan-y;
      user-select:none;
    }
    #herb-forum .tile{
      aspect-ratio:1;
      border:1px solid #ffffff18;
      border-radius:12px;
      display:grid;
      place-items:center;
      cursor:pointer;
      position:relative;
      overflow:hidden;
      background:linear-gradient(145deg,#5c785b,#3a5841);
      box-shadow:inset 0 1px #ffffff25, 0 2px 6px #00000025;
      transition:transform .12s, background .12s, box-shadow .12s;
    }
    #herb-forum .tile::before{
      content:"";
      position:absolute;
      inset:0;
      background:radial-gradient(circle at 50% 35%, var(--tileTint, #94b594), transparent 62%);
      opacity:.28;
      pointer-events:none;
    }
    #herb-forum .tile::after{
      content:"";
      position:absolute;
      inset:4px;
      border-radius:9px;
      border:1px solid #ffffff10;
      pointer-events:none;
    }
    #herb-forum .tile:hover{transform:translateY(-1px)}
    #herb-forum .tile:focus-visible{outline:3px solid #fff2bc;outline-offset:-3px}
    #herb-forum .tile.selected{
      background:linear-gradient(145deg,#8e7a46,#72613d);
      outline:3px solid #f9d48d;
      z-index:1;
      transform:scale(1.065);
      box-shadow:0 0 0 3px #f9d48d22, 0 8px 18px #0006;
    }
    #herb-forum .tile.hint{animation:hint 1s infinite}
    #herb-forum .herb-wrap{
      position:relative;
      z-index:1;
      display:grid;
      place-items:center;
      width:84%;
      height:84%;
      filter:drop-shadow(0 3px 2px #0004);
    }
    #herb-forum .herb-icon{
      width:100%;
      height:100%;
      display:block;
    }
    #herb-forum .tile.bad{animation:shake .22s}
    #herb-forum button{font:inherit}
    #herb-forum .bar{display:flex;justify-content:center;gap:9px;flex-wrap:wrap;margin-top:14px}
    #herb-forum .action{
      border:1px solid #648366;
      background:linear-gradient(180deg,#3c6549,#31563f);
      color:#f7eed5;
      border-radius:12px;
      padding:10px 15px;
      cursor:pointer;
      font-weight:650;
    }
    #herb-forum .action:hover{background:linear-gradient(180deg,#467853,#386746)}
    #herb-forum .legend{
      display:grid;
      grid-template-columns:repeat(2,minmax(0,1fr));
      gap:10px;
      justify-content:center;
      margin-top:17px;
    }
    #herb-forum .legend .legend-item{
      display:flex;
      align-items:center;
      gap:10px;
      font-size:12px;
      color:#ceddcc;
      background:#243b2f;
      border:1px solid #3f5d48;
      border-radius:12px;
      padding:7px 9px;
    }
    #herb-forum .legend .legend-item svg{width:30px;height:30px;flex:0 0 30px;filter:drop-shadow(0 2px 1px #0003)}
    #herb-forum .info{text-align:center;min-height:38px;margin:13px 0 0;color:#f4d992;font-size:14px}
    #herb-forum .overlay{position:fixed;inset:0;background:#07110ccc;display:none;place-items:center;padding:20px;z-index:10}
    #herb-forum .overlay.show{display:grid}
    #herb-forum .modal{
      max-width:370px;
      width:100%;
      background:#254231;
      border:1px solid #94a77a;
      border-radius:20px;
      padding:24px;
      text-align:center;
      box-shadow:0 15px 80px #000a;
    }
    #herb-forum .modal h2{font-family:Georgia,serif;font-size:28px;color:#f4da9e;margin:0 0 10px}
    #herb-forum .modal p{line-height:1.5;color:#dfebd8}
    #herb-forum .sr-only{
      position:absolute;
      width:1px;
      height:1px;
      padding:0;
      margin:-1px;
      overflow:hidden;
      clip:rect(0,0,0,0);
      white-space:nowrap;
      border:0;
    }
    @keyframes  hint{50%{box-shadow:0 0 0 4px #f8df93}}
    @keyframes  shake{25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
    @media (max-width:520px){#herb-forum .legend{grid-template-columns:1fr 1fr}}
    @media (max-width:420px){#herb-forum .game{padding:11px}
    #herb-forum .board{gap:3px;border-width:5px}
    #herb-forum .tile{border-radius:9px}
    #herb-forum .legend{grid-template-columns:1fr}}
    #herb-forum .goals{display:flex;justify-content:center;gap:9px;flex-wrap:wrap;margin:0 0 12px}
    #herb-forum .goal-chip{display:flex;align-items:center;gap:7px;background:#263f31;border:1px solid #557353;border-radius:13px;padding:5px 11px;font-size:13px}
    #herb-forum .goal-chip svg{width:29px;height:29px;filter:drop-shadow(0 2px 2px #0005)}
    #herb-forum .goal-chip.done{border-color:#e8d392;background:#435537}
    #herb-forum .tile{will-change:transform}
    #herb-forum .tile.striped:after{border:3px dashed #f9ecad;inset:4px;box-shadow:0 0 7px #eed28d}
    #herb-forum .tile.burst:after{border:3px solid #fac883;inset:6px;border-radius:50%;box-shadow:0 0 12px #f8bc60}
    #herb-forum .tile.bomb{background:radial-gradient(circle,#8460a1,#374a55)}
    #herb-forum .special-mark{position:absolute;right:0;bottom:0;background:#203326ed;color:#fff2bb;font-size:12px;line-height:17px;width:18px;height:18px;border-radius:8px 0 5px 0;z-index:3;text-align:center;font-weight:800}
    #herb-forum .bomb-core{width:74%;height:74%;border-radius:50%;display:grid;place-items:center;background:conic-gradient(#f5c85b,#f18c80,#aa86f0,#72c1aa,#f5c85b);border:3px solid #f8e6a9;box-shadow:0 0 16px #ffdf70a0,inset 0 0 0 5px #322a40;position:relative}
    #herb-forum .bomb-core:after{content:"✦";font-size:clamp(15px,3.4vw,27px);color:#fff4ca;text-shadow:0 0 8px white}
    #herb-forum .tile.disappear{animation:vanish .27s ease-in forwards}
    #herb-forum .tile.spawn{animation:spawn .33s cubic-bezier(.2,.7,.2,1) both}
    @keyframes  vanish{to{opacity:0;transform:scale(.18) rotate(20deg);filter:brightness(2)}}
    @keyframes  spawn{from{opacity:0;transform:translateY(-40px) scale(.72)}to{opacity:1;transform:translateY(0) scale(1)}}
    @media (prefers-reduced-motion:reduce){#herb-forum .tile, #herb-forum .tile.disappear, #herb-forum .tile.spawn{animation-duration:.01ms!important;transition:none!important}}
    #herb-forum{width:100%;max-width:640px;margin:12px auto;color:#f8ebcf;font-family:system-ui,-apple-system,Segoe UI,sans-serif}#herb-forum,#herb-forum *{box-sizing:border-box}#herb-forum .game{width:100%;}#herb-forum .forum-toggle{width:100%;padding:13px 15px;background:#274333;color:#f2dfaf;border:1px solid #6b8558;border-radius:14px;cursor:pointer;text-align:left;font-weight:700}#herb-forum .forum-content[hidden]{display:none!important}#herb-forum .forum-content{padding-top:9px}#herb-forum .tile{padding:0}#herb-forum .board{width:100%}#herb-forum .tile svg{display:block}
    </style>
    <div id="herb-forum">
    <button class="forum-toggle" type="button" id="herb-toggle" aria-expanded="false">✦ Травяная поляна · Открыть игру ▾</button>
    <div class="forum-content" id="herb-content" hidden>
    <svg width="0" height="0" aria-hidden="true" focusable="false" class="sr-only"> height="0" aria-hidden="true" focusable="false" class="sr-only">
      <defs>
        <linearGradient id="leafGreen" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#8fd26b"/>
          <stop offset="1" stop-color="#3f8b40"/>
        </linearGradient>
        <linearGradient id="leafDark" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#75bb55"/>
          <stop offset="1" stop-color="#2f6f35"/>
        </linearGradient>
        <linearGradient id="stem" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0" stop-color="#89c96f"/>
          <stop offset="1" stop-color="#44753f"/>
        </linearGradient>
        <linearGradient id="purpleBloom" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0" stop-color="#d8b8ff"/>
          <stop offset="1" stop-color="#8f61d9"/>
        </linearGradient>
        <linearGradient id="poppyRed" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#ff8f7e"/>
          <stop offset="1" stop-color="#d5362d"/>
        </linearGradient>
        <radialGradient id="goldCenter" cx="50%" cy="50%" r="60%">
          <stop offset="0" stop-color="#ffe894"/>
          <stop offset="1" stop-color="#d7a83d"/>
        </radialGradient>
        <linearGradient id="berryBlue" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#8bc7ff"/>
          <stop offset="1" stop-color="#4569bb"/>
        </linearGradient>
        <linearGradient id="lavenderPurple" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0" stop-color="#d7c1ff"/>
          <stop offset="1" stop-color="#7a59d1"/>
        </linearGradient>
        <linearGradient id="marigoldOrange" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#ffd16a"/>
          <stop offset="1" stop-color="#ef7d24"/>
        </linearGradient>

        <symbol id="herb-catmint" viewBox="0 0 64 64">
          <path d="M32 54C30 40 31 25 32 10" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 29C22 26 18 22 16 16C24 15 29 18 33 26" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <path d="M33 33C42 30 47 24 49 18C40 19 36 23 31 31" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <path d="M31 42C22 41 17 44 14 49C23 51 28 49 33 44" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <path d="M34 45C42 43 47 46 50 52C42 53 38 51 32 47" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <g stroke="#7d51c5" stroke-width="1">
            <ellipse cx="34" cy="14" rx="4.5" ry="5.2" fill="url(#purpleBloom)"/>
            <ellipse cx="29" cy="18" rx="4.2" ry="4.8" fill="url(#purpleBloom)"/>
            <ellipse cx="36.5" cy="20" rx="4" ry="4.6" fill="url(#purpleBloom)"/>
            <ellipse cx="31.5" cy="24" rx="3.8" ry="4.4" fill="url(#purpleBloom)"/>
          </g>
        </symbol>

        <symbol id="herb-poppy" viewBox="0 0 64 64">
          <path d="M32 53C32 41 32 30 31 16" fill="none" stroke="url(#stem)" stroke-width="3.2" stroke-linecap="round"/>
          <path d="M28 26C22 27 18 31 18 37C24 37 28 35 31 31" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M35 29C41 29 46 32 48 38C41 38 37 36 32 32" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g stroke="#b2231d" stroke-width="1.2">
            <path d="M32 13C25 7 18 12 19 21C24 21 28 19 32 16" fill="url(#poppyRed)"/>
            <path d="M32 13C39 7 46 12 45 21C40 21 36 19 32 16" fill="url(#poppyRed)"/>
            <path d="M32 13C24 15 22 24 27 29C30 25 31 21 32 16" fill="url(#poppyRed)"/>
            <path d="M32 13C40 15 42 24 37 29C34 25 33 21 32 16" fill="url(#poppyRed)"/>
          </g>
          <circle cx="32" cy="16" r="5.2" fill="#342a2a"/>
          <circle cx="32" cy="16" r="2" fill="#f2d96a"/>
        </symbol>

        <symbol id="herb-camomile" viewBox="0 0 64 64">
          <path d="M31 53C31 42 31 27 32 14" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 33C24 31 20 27 18 22C24 21 28 24 32 30" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M33 39C40 37 45 40 48 46C41 47 37 45 31 40" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g fill="#fffdf6" stroke="#e2dfd2" stroke-width="0.9">
            <ellipse cx="32" cy="12" rx="4" ry="11"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(30 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(60 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(90 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(120 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(150 32 12)"/>
          </g>
          <circle cx="32" cy="12" r="7" fill="url(#goldCenter)" stroke="#cc9830" stroke-width="1"/>
        </symbol>

        <symbol id="herb-juniper" viewBox="0 0 64 64">
          <path d="M16 45C28 36 39 27 50 14" fill="none" stroke="#59854c" stroke-width="3" stroke-linecap="round"/>
          <g stroke="#4d7a46" stroke-width="2" stroke-linecap="round">
            <path d="M20 41L14 31"/>
            <path d="M24 37L15 25"/>
            <path d="M29 33L20 21"/>
            <path d="M35 28L26 16"/>
            <path d="M26 39L15 40"/>
            <path d="M33 33L22 34"/>
            <path d="M40 27L29 27"/>
            <path d="M46 21L36 20"/>
          </g>
          <g>
            <circle cx="24" cy="44" r="6.3" fill="url(#berryBlue)" stroke="#385796" stroke-width="1.1"/>
            <circle cx="34" cy="36" r="6" fill="url(#berryBlue)" stroke="#385796" stroke-width="1.1"/>
            <circle cx="43" cy="27" r="5.5" fill="url(#berryBlue)" stroke="#385796" stroke-width="1.1"/>
            <circle cx="22" cy="43" r="1.2" fill="#d8efff" opacity=".8"/>
            <circle cx="32" cy="35" r="1.1" fill="#d8efff" opacity=".8"/>
            <circle cx="41.5" cy="26" r="1" fill="#d8efff" opacity=".8"/>
          </g>
        </symbol>

        <symbol id="herb-sorrel" viewBox="0 0 64 64">
          <path d="M32 53C31 39 31 27 32 14" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M32 17C22 17 15 22 12 33C21 34 28 30 32 21" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.3"/>
          <path d="M32 17C42 17 49 22 52 33C43 34 36 30 32 21" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.3"/>
          <path d="M30 34C23 34 18 39 16 47C23 48 28 45 31 38" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.3"/>
          <path d="M34 34C41 34 46 39 48 47C41 48 36 45 33 38" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.3"/>
        </symbol>

        <symbol id="herb-marigold" viewBox="0 0 64 64">
          <path d="M31 53C31 44 31 31 31 16" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 31C24 29 20 25 18 20C24 20 28 22 31 28" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M31 39C38 37 43 40 46 46C39 47 35 45 31 40" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g fill="url(#marigoldOrange)" stroke="#d56a18" stroke-width="0.9">
            <ellipse cx="32" cy="14" rx="4.3" ry="11"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(22.5 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(45 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(67.5 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(90 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(112.5 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(135 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(157.5 32 14)"/>
          </g>
          <circle cx="32" cy="14" r="6" fill="#f5a11c" stroke="#cf7414" stroke-width="1"/>
        </symbol>

        <symbol id="herb-lavender" viewBox="0 0 64 64">
          <path d="M32 54C31 41 32 27 32 12" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 38C24 36 20 32 18 27C24 26 28 29 31 35" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M33 43C39 41 44 43 48 49C41 50 37 48 32 44" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g fill="url(#lavenderPurple)" stroke="#704bbb" stroke-width=".9">
            <ellipse cx="32" cy="13" rx="4.2" ry="5.4"/>
            <ellipse cx="28.7" cy="18" rx="3.8" ry="5.1"/>
            <ellipse cx="35.3" cy="18" rx="3.8" ry="5.1"/>
            <ellipse cx="29.5" cy="23.2" rx="3.7" ry="4.8"/>
            <ellipse cx="34.5" cy="23.2" rx="3.7" ry="4.8"/>
            <ellipse cx="32" cy="28" rx="3.6" ry="4.6"/>
          </g>
        </symbol>
      </defs>
    </svg>
    <main class="game">
      <header>
        <h1>✦ Травяная поляна ✦</h1>
        <p>Собери запасы для палатки целителя</p>
      </header>

      <div class="stats">
        <div class="stat"><small>Очки</small><b id="score">0</b></div>
        <div class="stat"><small>Ходы</small><b id="moves">25</b></div>
        <div class="stat"><small>Рекорд</small><b id="best">0</b></div>
      </div>

      <p class="goal">За 25 ходов собери травы для целителя</p><div class="goals" id="goals" aria-label="Задания по сбору трав"></div>
      <div class="board" id="board" role="group" aria-label="Поле три в ряд, восемь на восемь"></div>

      <div class="bar">
        <button class="action" id="hint">✦ Подсказка</button>
        <button class="action" id="restart">↻ Новая игра</button>
      </div>

      <p class="info" id="info" aria-live="polite">Меняй местами соседние травы, чтобы собрать 3 и больше в ряд.</p>
      <div class="legend" id="legend"></div>
    </main>
    <div class="overlay" id="overlay">
      <div class="modal">
        <h2 id="endTitle"></h2>
        <p id="endText"></p>
        <button class="action" id="again">Сыграть ещё</button>
      </div>
    </div>

    </div>
    </div>
    <script>
    (function(){const button=document.getElementById('herb-toggle'),content=document.getElementById('herb-content');if(!button||button.dataset.bound)return;button.dataset.bound='1';button.addEventListener('click',()=>{const open=content.hidden;content.hidden=!open;button.setAttribute('aria-expanded',String(open));button.textContent=open?'✦ Травяная поляна · Свернуть игру ▴':'✦ Травяная поляна · Открыть игру ▾';})})();
    </script>
    <script>
    (()=>{
    'use strict';
    if(!document.getElementById('herb-forum'))return;
    const N=8,MAX_MOVES=25;
    const herbs=[
    {name:'Кошачья мята',id:'catmint',tint:'#93d071'},
    {name:'Мак',id:'poppy',tint:'#db685f'},
    {name:'Ромашка',id:'camomile',tint:'#f0dd95'},
    {name:'Можжевельник',id:'juniper',tint:'#6ea8d9'},
    {name:'Щавель',id:'sorrel',tint:'#7fc16a'},
    {name:'Календула',id:'marigold',tint:'#efad4d'}
    ];
    const el=id=>document.getElementById(id),boardEl=el('board');
    const pause=ms=>new Promise(r=>setTimeout(r,ms));
    const idx=(r,c)=>r*N+c,row=i=>Math.floor(i/N),col=i=>i%N;
    const adjacent=(a,b)=>Math.abs(row(a)-row(b))+Math.abs(col(a)-col(b))===1;
    const random=()=>Math.floor(Math.random()*herbs.length);
    let nextId=0,board=[],score=0,moves=MAX_MOVES,selected=null,busy=false,ended=false;
    let hintTimer=null,session=0,goals=[];
    let best=0;try{best=Number(localStorage.getItem('herbMatchBest')||0)}catch{}
    const piece=(type,special=null)=>({id:++nextId,type,special});
    const symbol=h=>`<svg viewBox="0 0 64 64" aria-hidden="true"><use href="#herb-${h.id}"></use></svg>`;
    el('legend').innerHTML=herbs.map(h=>`<div class="legend-item">${symbol(h)}<span>${h.name}</span></div>`).join('');
    function say(t){el('info').textContent=t}
    function update(){
    el('score').textContent=score;el('moves').textContent=moves;el('best').textContent=best;
    el('goals').innerHTML=goals.map(g=>`<div class="goal-chip ${g.left===0?'done':''}">${symbol(herbs[g.type])}<span>${herbs[g.type].name}: <b>${g.left===0?'✓':g.left}</b></span></div>`).join('');
    }
    function scan(b){
    const groups=[];const get=i=>b[i]?.type;
    for(let r=0;r<N;r++){let c=0;while(c<N){let e=c+1;while(e<N&&get(idx(r,c))!=null&&get(idx(r,e))===get(idx(r,c)))e++;if(get(idx(r,c))!=null&&e-c>=3)groups.push({line:Array.from({length:e-c},(_,k)=>idx(r,c+k)),dir:'row'});c=e}}
    for(let c=0;c<N;c++){let r=0;while(r<N){let e=r+1;while(e<N&&get(idx(r,c))!=null&&get(idx(e,c))===get(idx(r,c)))e++;if(get(idx(r,c))!=null&&e-r>=3)groups.push({line:Array.from({length:e-r},(_,k)=>idx(r+k,c)),dir:'col'});r=e}}
    // 2x2 squares produce an exploding herb even if they do not form a line.
    const squares=[];for(let r=0;r<N-1;r++)for(let c=0;c<N-1;c++){const sq=[idx(r,c),idx(r+1,c),idx(r,c+1),idx(r+1,c+1)];if(get(sq[0])!=null&&sq.every(i=>get(i)===get(sq[0])))squares.push(sq)}
    return {groups,squares};
    }
    function canMove(a,b){
    if(board[a]?.special==='bomb'||board[b]?.special==='bomb')return true;
    [board[a],board[b]]=[board[b],board[a]];
    const s=scan(board);const ok=s.groups.length>0||s.squares.length>0;
    [board[a],board[b]]=[board[b],board[a]];
    return ok;
    }
    function validMoves(){
    const result=[];for(let i=0;i<N*N;i++)for(const j of [i+1,i+N])if(j<N*N&&adjacent(i,j)&&canMove(i,j))result.push([i,j]);
    return result;
    }
    function fresh(){
    for(let attempt=0;attempt<200;attempt++){
    board=Array(N*N).fill(null);
    for(let i=0;i<board.length;i++){
    const choices=herbs.map((_,k)=>k).filter(t=>!(col(i)>=2&&board[i-1]?.type===t&&board[i-2]?.type===t)&&!(row(i)>=2&&board[i-N]?.type===t&&board[i-2*N]?.type===t)&&!(row(i)>=1&&col(i)>=1&&board[i-1]?.type===t&&board[i-N]?.type===t&&board[i-N-1]?.type===t));
    board[i]=piece(choices[Math.floor(Math.random()*choices.length)]);
    }
    if(validMoves().length)return;
    }
    }
    function draw({animate=true}={}){
    const previous=new Map();
    if(animate)for(const node of boardEl.children)previous.set(Number(node.dataset.id),node.getBoundingClientRect());
    const fragment=document.createDocumentFragment();
    board.forEach((p,i)=>{
    const node=document.createElement('button');node.type='button';node.className='tile'+(selected===i?' selected':'')+(p?.special?' '+p.special:'');
    node.dataset.i=i;node.dataset.id=p?.id||0;
    node.setAttribute('aria-label',`Ряд ${row(i)+1}, столбец ${col(i)+1}: ${p?(p.special?p.special+' ':'')+(p.special==='bomb'?'Цветная бомба':herbs[p.type].name):'пусто'}`);
    if(p){
    node.style.setProperty('--tileTint',p.type==null?'#a98be4':herbs[p.type].tint);
    node.innerHTML=p.special==='bomb'?'<span class="bomb-core" aria-hidden="true"></span>':`<span class="herb-wrap" aria-hidden="true">${symbol(herbs[p.type])}</span>${p.special?'<span class="special-mark" aria-hidden="true">'+(p.special==='striped'?'↔':'✦')+'</span>':''}`;
    }
    fragment.append(node);
    });
    boardEl.replaceChildren(fragment);
    if(!animate)return;
    for(const node of boardEl.children){
    const p=previous.get(Number(node.dataset.id));
    if(p&&Number(node.dataset.id)>0){
    const now=node.getBoundingClientRect(),dx=p.left-now.left,dy=p.top-now.top;
    if(Math.abs(dx)+Math.abs(dy)>1)node.animate([{transform:`translate(${dx}px,${dy}px)`,zIndex:4},{transform:'translate(0,0)',zIndex:1}],{duration:300,easing:'cubic-bezier(.22,.8,.24,1)'});
    }else if(Number(node.dataset.id)>0){node.classList.add('spawn');node.addEventListener('animationend',()=>node.classList.remove('spawn'),{once:true})}
    }
    }
    function swap(a,b){[board[a],board[b]]=[board[b],board[a]]}
    function addScore(amount){score+=amount;if(score>best){best=score;try{localStorage.setItem('herbMatchBest',String(best))}catch{}}}
    function refill(){
    for(let c=0;c<N;c++){let target=N-1;for(let r=N-1;r>=0;r--)if(board[idx(r,c)]!==null){board[idx(target,c)]=board[idx(r,c)];if(target!==r)board[idx(r,c)]=null;target--}
    while(target>=0)board[idx(target--,c)]=piece(random());
    }
    }
    function chosenSpecial(s,anchor){
    // Priorities: five-line color bomb, 4-line stripe, 2x2 burst.
    const options=[];
    for(const g of s.groups)if(g.line.length>=5)options.push({indices:g.line,special:'bomb',power:30});
    for(const g of s.groups)if(g.line.length===4)options.push({indices:g.line,special:'striped',power:20});
    for(const sq of s.squares)options.push({indices:sq,special:'burst',power:10});
    options.sort((a,b)=>b.power-a.power);
    if(!options.length)return null;
    const o=options[0];
    const position=o.indices.includes(anchor)?anchor:o.indices[Math.floor(o.indices.length/2)];
    return {...o,position};
    }
    function effectIndices(i,p,remove){
    if(p.special==='striped'){
      for(let c=0;c<N;c++)remove.add(idx(row(i),c));
      for(let r=0;r<N;r++)remove.add(idx(r,col(i)));
    }else if(p.special==='burst'){
      for(let r=Math.max(0,row(i)-1);r<=Math.min(N-1,row(i)+1);r++)for(let c=Math.max(0,col(i)-1);c<=Math.min(N-1,col(i)+1);c++)remove.add(idx(r,c));
    }
    }
    async function resolve(anchor=-1,forced=null,run=session){
    let chain=0;
    while(run===session){
      const s=scan(board);
      if(!s.groups.length&&!s.squares.length&&!forced?.size)break;
      chain++;
      const remove=new Set(forced||[]);
      forced=null;
      for(const g of s.groups)g.line.forEach(i=>remove.add(i));
      for(const sq of s.squares)sq.forEach(i=>remove.add(i));
      const make=chosenSpecial(s,anchor);
      const protectedIndex=make?.position;
      // A newly created special piece is kept in the board.
      if(make&&board[protectedIndex]){
       board[protectedIndex]={...board[protectedIndex],special:make.special,type:make.special==='bomb'?null:board[protectedIndex].type};
       remove.delete(protectedIndex);
      }
      const activated=new Set();
      let expand=true;
      while(expand){
       expand=false;
       for(const i of [...remove]){
        const p=board[i];
        if(!p||!p.special||p.special==='bomb'||activated.has(p.id))continue;
        activated.add(p.id);const count=remove.size;effectIndices(i,p,remove);
        if(remove.size>count)expand=true;
       }
      }
      const gathered=new Map();
      for(const i of remove)if(board[i]?.type!=null)gathered.set(board[i].type,(gathered.get(board[i].type)||0)+1);
      for(const g of goals)g.left=Math.max(0,g.left-(gathered.get(g.type)||0));
      addScore(remove.size*60*chain+(make?150:0));
      say(make?`Создан бонус: ${make.special==='bomb'?'цветная бомба':make.special==='striped'?'полосатая трава':'взрывная трава'}!`:chain>1?`Каскад ×${chain}! Собрано ${remove.size} трав.`:`Собрано ${remove.size} трав!`);
      update();draw();
      await pause(160);if(run!==session)return;
      for(const i of remove){const node=boardEl.children[i];if(node)node.classList.add('disappear')}
      await pause(250);if(run!==session)return;
      for(const i of remove)board[i]=null;
      refill();draw();await pause(330);
      anchor=-1;
    }
    }
    async function activateBomb(a,b,run){
    const first=board[a],second=board[b],remove=new Set([a,b]);
    if(first.special==='bomb'&&second.special==='bomb'){
      for(let i=0;i<N*N;i++)remove.add(i);
    }else{
      const other=first.special==='bomb'?second:first;
      if(other.type!=null)for(let i=0;i<N*N;i++)if(board[i]?.type===other.type)remove.add(i);
    }
    // Bomb interactions with other specials also trigger their abilities.
    const expanded=new Set();
    for(const i of [...remove])if(board[i]?.special&&board[i].special!=='bomb'&&!expanded.has(i)){expanded.add(i);effectIndices(i,board[i],remove)}
    await resolve(-1,remove,run);
    }
    function finish(){
    ended=true;const won=goals.every(g=>g.left===0);
    el('endTitle').textContent=won?'Все травы собраны!':'Запасы закончились';
    el('endText').textContent=won?`Целитель получил все травы! Результат: ${score} очков.`:`Набрано ${score} очков. Не хватило: ${goals.filter(g=>g.left).map(g=>herbs[g.type].name+' ×'+g.left).join(', ')}.`;
    el('overlay').classList.add('show');
    }
    async function play(a,b){
    if(busy||ended||!adjacent(a,b))return;
    busy=true;selected=null;const run=session;
    const specialBomb=board[a]?.special==='bomb'||board[b]?.special==='bomb';
    swap(a,b);draw();await pause(300);
    if(run!==session)return;
    const s=scan(board);
    if(!specialBomb&&!s.groups.length&&!s.squares.length){
      swap(a,b);draw();say('Нужно собрать ряд из 3 трав или квадрат 2×2.');busy=false;return;
    }
    moves--;update();
    if(specialBomb)await activateBomb(a,b,run);else await resolve(b,null,run);
    if(run!==session)return;
    if(goals.every(g=>g.left===0)||moves<=0){finish();busy=false;return}
    if(!validMoves().length){say('Ходов нет — перемешиваем поляну.');await pause(300);if(run!==session)return;shuffle()}
    busy=false;
    }
    function shuffle(){
    const pieces=board.slice();
    for(let t=0;t<300;t++){
      for(let i=pieces.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[pieces[i],pieces[j]]=[pieces[j],pieces[i]]}
      board=pieces.slice();const s=scan(board);if(!s.groups.length&&!s.squares.length&&validMoves().length){draw();return}
    }
    fresh();draw();
    }
    function choose(i){
    if(busy||ended)return;
    if(selected===null){selected=i;draw({animate:false});return}
    if(selected===i){selected=null;draw({animate:false});return}
    const a=selected;
    if(adjacent(a,i))play(a,i);else{selected=i;draw({animate:false})}
    }
    let suppressClick=false,start=null;
    boardEl.addEventListener('click',e=>{if(suppressClick){suppressClick=false;return}const node=e.target.closest('.tile');if(node)choose(Number(node.dataset.i))});
    boardEl.addEventListener('pointerdown',e=>{const node=e.target.closest('.tile');if(node)start={i:Number(node.dataset.i),x:e.clientX,y:e.clientY}});
    boardEl.addEventListener('pointerup',e=>{
    if(!start||busy||ended)return;
    const dx=e.clientX-start.x,dy=e.clientY-start.y;
    if(Math.max(Math.abs(dx),Math.abs(dy))>22){
      const r=row(start.i)+(Math.abs(dy)>Math.abs(dx)?Math.sign(dy):0);
      const c=col(start.i)+(Math.abs(dx)>=Math.abs(dy)?Math.sign(dx):0);
      if(r>=0&&r<N&&c>=0&&c<N){suppressClick=true;play(start.i,idx(r,c))}
    }
    start=null;
    });
    boardEl.addEventListener('pointercancel',()=>start=null);
    el('hint').addEventListener('click',()=>{
    if(busy||ended)return;
    const list=validMoves();if(!list.length)return;
    const pair=list[Math.floor(Math.random()*list.length)];
    boardEl.querySelectorAll('.hint').forEach(n=>n.classList.remove('hint'));
    pair.forEach(i=>boardEl.children[i].classList.add('hint'));
    say('Перемести одну подсвеченную траву на место другой.');
    clearTimeout(hintTimer);hintTimer=setTimeout(()=>boardEl.querySelectorAll('.hint').forEach(n=>n.classList.remove('hint')),2200);
    });
    function reset(){
    session++;clearTimeout(hintTimer);score=0;moves=MAX_MOVES;selected=null;busy=false;ended=false;
    el('overlay').classList.remove('show');
    const chosen=herbs.map((_,i)=>i).sort(()=>Math.random()-.5).slice(0,3);
    goals=chosen.map((type,i)=>({type,left:[12,10,8][i]}));
    fresh();draw({animate:false});update();
    say('3 в ряд — сбор. 4 в ряд — полосатая трава. Квадрат 2×2 — взрыв. 5 в ряд — цветная бомба.');
    }
    el('restart').addEventListener('click',reset);
    el('again').addEventListener('click',reset);
    reset();
    })();
    </script>
    [/html]

    UPD: другая версия, должна быть с прогрессирующей сложностью

    [html]
    <style>
    #herb-forum{
      --bg:#101d19;
      --panel:#20372b;
      --panel-2:#2b4736;
      --cream:#f8ebcf;
      --mint:#a6d99a;
      --gold:#e9c77e;
      --line:#5d7454;
    }
    #herb-forum *{box-sizing:border-box}
    #herb-forum{font-family:system-ui,-apple-system,Segoe UI,sans-serif;color:#f8ebcf;
     
     
     
     
     
      font-family:system-ui,-apple-system,Segoe UI,sans-serif;
      color:var(--cream);
     
    }
    #herb-forum .game{
      width:min(100%,640px);
      background:linear-gradient(180deg,#22382d 0%,#17271f 100%);
      border:1px solid var(--line);
      border-radius:28px;
      padding:clamp(13px,3vw,24px);
      box-shadow:0 24px 80px #0007;
    }
    #herb-forum header{text-align:center}
    #herb-forum h1{
      font-family:Georgia,serif;
      margin:0;
      font-size:clamp(29px,6vw,39px);
      font-weight:500;
      color:#f6dfab;
      letter-spacing:.02em;
    }
    #herb-forum header p{
      margin:7px 0 16px;
      color:#b3cbb4;
      font-size:14px;
    }
    #herb-forum .stats{
      display:grid;
      grid-template-columns:repeat(3,1fr);
      gap:8px;
      margin-bottom:14px;
    }
    #herb-forum .stat{
      background:linear-gradient(180deg,#314f3d,#294436);
      border:1px solid #49634c;
      border-radius:13px;
      padding:9px;
      text-align:center;
    }
    #herb-forum .stat small{
      display:block;
      font-size:11px;
      text-transform:uppercase;
      letter-spacing:.11em;
      color:#bad2bd;
    }
    #herb-forum .stat b{font-size:24px;color:#fff0c7}
    #herb-forum .goal{text-align:center;margin:0 0 12px;color:#cbdabc;font-size:13px}
    #herb-forum .board{
      display:grid;
      grid-template-columns:repeat(8,1fr);
      gap:5px;
      background:
        linear-gradient(180deg,#38553f,#314c38);
      border:7px solid #395741;
      border-radius:20px;
      padding:2px;
      touch-action:pan-y;
      user-select:none;
    }
    #herb-forum .tile{
      aspect-ratio:1;
      border:1px solid #ffffff18;
      border-radius:12px;
      display:grid;
      place-items:center;
      cursor:pointer;
      position:relative;
      overflow:hidden;
      background:linear-gradient(145deg,#5c785b,#3a5841);
      box-shadow:inset 0 1px #ffffff25, 0 2px 6px #00000025;
      transition:transform .12s, background .12s, box-shadow .12s;
    }
    #herb-forum .tile::before{
      content:"";
      position:absolute;
      inset:0;
      background:radial-gradient(circle at 50% 35%, var(--tileTint, #94b594), transparent 62%);
      opacity:.28;
      pointer-events:none;
    }
    #herb-forum .tile::after{
      content:"";
      position:absolute;
      inset:4px;
      border-radius:9px;
      border:1px solid #ffffff10;
      pointer-events:none;
    }
    #herb-forum .tile:hover{transform:translateY(-1px)}
    #herb-forum .tile:focus-visible{outline:3px solid #fff2bc;outline-offset:-3px}
    #herb-forum .tile.selected{
      background:linear-gradient(145deg,#8e7a46,#72613d);
      outline:3px solid #f9d48d;
      z-index:1;
      transform:scale(1.065);
      box-shadow:0 0 0 3px #f9d48d22, 0 8px 18px #0006;
    }
    #herb-forum .tile.hint{animation:hint 1s infinite}
    #herb-forum .herb-wrap{
      position:relative;
      z-index:1;
      display:grid;
      place-items:center;
      width:100%;
      height:100%;
      filter:drop-shadow(0 3px 2px #0004);
    }
    #herb-forum .herb-icon{
      width:100%;
      height:100%;
      display:block;
    }
    #herb-forum .tile.bad{animation:shake .22s}
    #herb-forum button{font:inherit}
    #herb-forum .bar{display:flex;justify-content:center;gap:9px;flex-wrap:wrap;margin-top:14px}
    #herb-forum .action{
      border:1px solid #648366;
      background:linear-gradient(180deg,#3c6549,#31563f);
      color:#f7eed5;
      border-radius:12px;
      padding:10px 15px;
      cursor:pointer;
      font-weight:650;
    }
    #herb-forum .action:hover{background:linear-gradient(180deg,#467853,#386746)}
    #herb-forum .legend{
      display:grid;
      grid-template-columns:repeat(2,minmax(0,1fr));
      gap:10px;
      justify-content:center;
      margin-top:17px;
    }
    #herb-forum .legend .legend-item{
      display:flex;
      align-items:center;
      gap:10px;
      font-size:12px;
      color:#ceddcc;
      background:#243b2f;
      border:1px solid #3f5d48;
      border-radius:12px;
      padding:7px 9px;
    }
    #herb-forum .legend .legend-item svg{width:30px;height:30px;flex:0 0 30px;filter:drop-shadow(0 2px 1px #0003)}
    #herb-forum .info{text-align:center;min-height:38px;margin:13px 0 0;color:#f4d992;font-size:14px}
    #herb-forum .overlay{position:fixed;inset:0;background:#07110ccc;display:none;place-items:center;padding:20px;z-index:10}
    #herb-forum .overlay.show{display:grid}
    #herb-forum .modal{
      max-width:370px;
      width:100%;
      background:#254231;
      border:1px solid #94a77a;
      border-radius:20px;
      padding:24px;
      text-align:center;
      box-shadow:0 15px 80px #000a;
    }
    #herb-forum .modal h2{font-family:Georgia,serif;font-size:28px;color:#f4da9e;margin:0 0 10px}
    #herb-forum .modal p{line-height:1.5;color:#dfebd8}
    #herb-forum .sr-only{
      position:absolute;
      width:1px;
      height:1px;
      padding:0;
      margin:-1px;
      overflow:hidden;
      clip:rect(0,0,0,0);
      white-space:nowrap;
      border:0;
    }
    @keyframes  hint{50%{box-shadow:0 0 0 4px #f8df93}}
    @keyframes  shake{25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
    @media (max-width:520px){#herb-forum .legend{grid-template-columns:1fr 1fr}}
    @media (max-width:420px){#herb-forum .game{padding:11px}
    #herb-forum .board{gap:3px;border-width:5px}
    #herb-forum .tile{border-radius:9px}
    #herb-forum .legend{grid-template-columns:1fr}}
    #herb-forum .goals{display:flex;justify-content:center;gap:9px;flex-wrap:wrap;margin:0 0 12px}
    #herb-forum .goal-chip{display:flex;align-items:center;gap:7px;background:#263f31;border:1px solid #557353;border-radius:13px;padding:5px 11px;font-size:13px}
    #herb-forum .goal-chip svg{width:29px;height:29px;filter:drop-shadow(0 2px 2px #0005)}
    #herb-forum .goal-chip.done{border-color:#e8d392;background:#435537}
    #herb-forum .tile{will-change:transform}
    #herb-forum .tile.striped:after{border:3px dashed #f9ecad;inset:4px;box-shadow:0 0 7px #eed28d}
    #herb-forum .tile.burst:after{border:3px solid #fac883;inset:6px;border-radius:50%;box-shadow:0 0 12px #f8bc60}
    #herb-forum .tile.bomb{background:radial-gradient(circle,#8460a1,#374a55)}
    #herb-forum .special-mark{position:absolute;right:0;bottom:0;background:#203326ed;color:#fff2bb;font-size:12px;line-height:17px;width:18px;height:18px;border-radius:8px 0 5px 0;z-index:3;text-align:center;font-weight:800}
    #herb-forum .bomb-core{width:74%;height:74%;border-radius:50%;display:grid;place-items:center;background:conic-gradient(#f5c85b,#f18c80,#aa86f0,#72c1aa,#f5c85b);border:3px solid #f8e6a9;box-shadow:0 0 16px #ffdf70a0,inset 0 0 0 5px #322a40;position:relative}
    #herb-forum .bomb-core:after{content:"✦";font-size:clamp(15px,3.4vw,27px);color:#fff4ca;text-shadow:0 0 8px white}
    #herb-forum .tile.disappear{animation:vanish .27s ease-in forwards}
    #herb-forum .tile.spawn{animation:spawn .33s cubic-bezier(.2,.7,.2,1) both}
    @keyframes  vanish{to{opacity:0;transform:scale(.18) rotate(20deg);filter:brightness(2)}}
    @keyframes  spawn{from{opacity:0;transform:translateY(-40px) scale(.72)}to{opacity:1;transform:translateY(0) scale(1)}}
    @media (prefers-reduced-motion:reduce){#herb-forum .tile, #herb-forum .tile.disappear, #herb-forum .tile.spawn{animation-duration:.01ms!important;transition:none!important}}
    #herb-forum{width:100%;max-width:640px;margin:12px auto;color:#f8ebcf;font-family:system-ui,-apple-system,Segoe UI,sans-serif}#herb-forum,#herb-forum *{box-sizing:border-box}#herb-forum .game{width:100%;}#herb-forum .forum-toggle{width:100%;padding:13px 15px;background:#274333;color:#f2dfaf;border:1px solid #6b8558;border-radius:14px;cursor:pointer;text-align:left;font-weight:700}#herb-forum .forum-content[hidden]{display:none!important}#herb-forum .forum-content{padding-top:9px}#herb-forum .tile{padding:0}#herb-forum .board{width:100%}#herb-forum .tile svg{display:block}

    #herb-forum .level-line{text-align:center;font-size:14px;color:#f4d99b;margin:1px 0 12px}
    #herb-forum .level-line strong{font-size:18px;color:#fff3d0}
    #herb-forum .tile .herb-wrap{width:100%;height:100%;transform:scale(1.13);transform-origin:center}
    #herb-forum .tile .herb-icon{width:100%;height:100%}
    #herb-forum .tile .special-mark{transform:scale(.82);transform-origin:bottom right}
    </style>
    <div id="herb-forum">
    <button class="forum-toggle" type="button" id="herb-toggle" aria-expanded="false">✦ Травяная поляна · Открыть игру ▾</button>
    <div class="forum-content" id="herb-content" hidden>
    <svg width="0" height="0" aria-hidden="true" focusable="false" class="sr-only"> height="0" aria-hidden="true" focusable="false" class="sr-only">
      <defs>
        <linearGradient id="leafGreen" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#8fd26b"/>
          <stop offset="1" stop-color="#3f8b40"/>
        </linearGradient>
        <linearGradient id="leafDark" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#75bb55"/>
          <stop offset="1" stop-color="#2f6f35"/>
        </linearGradient>
        <linearGradient id="stem" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0" stop-color="#89c96f"/>
          <stop offset="1" stop-color="#44753f"/>
        </linearGradient>
        <linearGradient id="purpleBloom" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0" stop-color="#d8b8ff"/>
          <stop offset="1" stop-color="#8f61d9"/>
        </linearGradient>
        <linearGradient id="poppyRed" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#ff8f7e"/>
          <stop offset="1" stop-color="#d5362d"/>
        </linearGradient>
        <radialGradient id="goldCenter" cx="50%" cy="50%" r="60%">
          <stop offset="0" stop-color="#ffe894"/>
          <stop offset="1" stop-color="#d7a83d"/>
        </radialGradient>
        <linearGradient id="berryBlue" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#8bc7ff"/>
          <stop offset="1" stop-color="#4569bb"/>
        </linearGradient>
        <linearGradient id="lavenderPurple" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0" stop-color="#d7c1ff"/>
          <stop offset="1" stop-color="#7a59d1"/>
        </linearGradient>
        <linearGradient id="marigoldOrange" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0" stop-color="#ffd16a"/>
          <stop offset="1" stop-color="#ef7d24"/>
        </linearGradient>

        <symbol id="herb-catmint" viewBox="0 0 64 64">
          <path d="M32 54C30 40 31 25 32 10" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 29C22 26 18 22 16 16C24 15 29 18 33 26" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <path d="M33 33C42 30 47 24 49 18C40 19 36 23 31 31" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <path d="M31 42C22 41 17 44 14 49C23 51 28 49 33 44" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <path d="M34 45C42 43 47 46 50 52C42 53 38 51 32 47" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.4" stroke-linejoin="round"/>
          <g stroke="#7d51c5" stroke-width="1">
            <ellipse cx="34" cy="14" rx="4.5" ry="5.2" fill="url(#purpleBloom)"/>
            <ellipse cx="29" cy="18" rx="4.2" ry="4.8" fill="url(#purpleBloom)"/>
            <ellipse cx="36.5" cy="20" rx="4" ry="4.6" fill="url(#purpleBloom)"/>
            <ellipse cx="31.5" cy="24" rx="3.8" ry="4.4" fill="url(#purpleBloom)"/>
          </g>
        </symbol>

        <symbol id="herb-poppy" viewBox="0 0 64 64">
          <path d="M32 53C32 41 32 30 31 16" fill="none" stroke="url(#stem)" stroke-width="3.2" stroke-linecap="round"/>
          <path d="M28 26C22 27 18 31 18 37C24 37 28 35 31 31" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M35 29C41 29 46 32 48 38C41 38 37 36 32 32" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g stroke="#b2231d" stroke-width="1.2">
            <path d="M32 13C25 7 18 12 19 21C24 21 28 19 32 16" fill="url(#poppyRed)"/>
            <path d="M32 13C39 7 46 12 45 21C40 21 36 19 32 16" fill="url(#poppyRed)"/>
            <path d="M32 13C24 15 22 24 27 29C30 25 31 21 32 16" fill="url(#poppyRed)"/>
            <path d="M32 13C40 15 42 24 37 29C34 25 33 21 32 16" fill="url(#poppyRed)"/>
          </g>
          <circle cx="32" cy="16" r="5.2" fill="#342a2a"/>
          <circle cx="32" cy="16" r="2" fill="#f2d96a"/>
        </symbol>

        <symbol id="herb-camomile" viewBox="0 0 64 64">
          <path d="M31 53C31 42 31 27 32 14" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 33C24 31 20 27 18 22C24 21 28 24 32 30" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M33 39C40 37 45 40 48 46C41 47 37 45 31 40" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g fill="#fffdf6" stroke="#e2dfd2" stroke-width="0.9">
            <ellipse cx="32" cy="12" rx="4" ry="11"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(30 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(60 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(90 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(120 32 12)"/>
            <ellipse cx="32" cy="12" rx="4" ry="11" transform="rotate(150 32 12)"/>
          </g>
          <circle cx="32" cy="12" r="7" fill="url(#goldCenter)" stroke="#cc9830" stroke-width="1"/>
        </symbol>

        <symbol id="herb-juniper" viewBox="0 0 64 64">
          <path d="M16 45C28 36 39 27 50 14" fill="none" stroke="#59854c" stroke-width="3" stroke-linecap="round"/>
          <g stroke="#4d7a46" stroke-width="2" stroke-linecap="round">
            <path d="M20 41L14 31"/>
            <path d="M24 37L15 25"/>
            <path d="M29 33L20 21"/>
            <path d="M35 28L26 16"/>
            <path d="M26 39L15 40"/>
            <path d="M33 33L22 34"/>
            <path d="M40 27L29 27"/>
            <path d="M46 21L36 20"/>
          </g>
          <g>
            <circle cx="24" cy="44" r="6.3" fill="url(#berryBlue)" stroke="#385796" stroke-width="1.1"/>
            <circle cx="34" cy="36" r="6" fill="url(#berryBlue)" stroke="#385796" stroke-width="1.1"/>
            <circle cx="43" cy="27" r="5.5" fill="url(#berryBlue)" stroke="#385796" stroke-width="1.1"/>
            <circle cx="22" cy="43" r="1.2" fill="#d8efff" opacity=".8"/>
            <circle cx="32" cy="35" r="1.1" fill="#d8efff" opacity=".8"/>
            <circle cx="41.5" cy="26" r="1" fill="#d8efff" opacity=".8"/>
          </g>
        </symbol>

        <symbol id="herb-sorrel" viewBox="0 0 64 64">
          <path d="M32 53C31 39 31 27 32 14" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M32 17C22 17 15 22 12 33C21 34 28 30 32 21" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.3"/>
          <path d="M32 17C42 17 49 22 52 33C43 34 36 30 32 21" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.3"/>
          <path d="M30 34C23 34 18 39 16 47C23 48 28 45 31 38" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.3"/>
          <path d="M34 34C41 34 46 39 48 47C41 48 36 45 33 38" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.3"/>
        </symbol>

        <symbol id="herb-marigold" viewBox="0 0 64 64">
          <path d="M31 53C31 44 31 31 31 16" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 31C24 29 20 25 18 20C24 20 28 22 31 28" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M31 39C38 37 43 40 46 46C39 47 35 45 31 40" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g fill="url(#marigoldOrange)" stroke="#d56a18" stroke-width="0.9">
            <ellipse cx="32" cy="14" rx="4.3" ry="11"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(22.5 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(45 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(67.5 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(90 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(112.5 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(135 32 14)"/>
            <ellipse cx="32" cy="14" rx="4.3" ry="11" transform="rotate(157.5 32 14)"/>
          </g>
          <circle cx="32" cy="14" r="6" fill="#f5a11c" stroke="#cf7414" stroke-width="1"/>
        </symbol>

        <symbol id="herb-lavender" viewBox="0 0 64 64">
          <path d="M32 54C31 41 32 27 32 12" fill="none" stroke="url(#stem)" stroke-width="3" stroke-linecap="round"/>
          <path d="M31 38C24 36 20 32 18 27C24 26 28 29 31 35" fill="url(#leafGreen)" stroke="#2d6e33" stroke-width="1.2"/>
          <path d="M33 43C39 41 44 43 48 49C41 50 37 48 32 44" fill="url(#leafDark)" stroke="#2d6e33" stroke-width="1.2"/>
          <g fill="url(#lavenderPurple)" stroke="#704bbb" stroke-width=".9">
            <ellipse cx="32" cy="13" rx="4.2" ry="5.4"/>
            <ellipse cx="28.7" cy="18" rx="3.8" ry="5.1"/>
            <ellipse cx="35.3" cy="18" rx="3.8" ry="5.1"/>
            <ellipse cx="29.5" cy="23.2" rx="3.7" ry="4.8"/>
            <ellipse cx="34.5" cy="23.2" rx="3.7" ry="4.8"/>
            <ellipse cx="32" cy="28" rx="3.6" ry="4.6"/>
          </g>
        </symbol>
      </defs>
    </svg>
    <main class="game">
      <header>
        <h1>✦ Травяная поляна ✦</h1>
        <p>Собери запасы для палатки целителя</p>
      </header>

      <p class="level-line">Уровень <strong id="level">1</strong> · <span id="levelNote">Знакомство с поляной</span></p>
      <div class="stats">
        <div class="stat"><small>Очки</small><b id="score">0</b></div>
        <div class="stat"><small>Ходы</small><b id="moves">25</b></div>
        <div class="stat"><small>Рекорд</small><b id="best">0</b></div>
      </div>

      <p class="goal">Собери травы за отведённые ходы</p><div class="goals" id="goals" aria-label="Задания по сбору трав"></div>
      <div class="board" id="board" role="group" aria-label="Поле три в ряд, восемь на восемь"></div>

      <div class="bar">
        <button class="action" id="hint">✦ Подсказка</button>
        <button class="action" id="restart">↻ Новая игра</button>
      </div>

      <p class="info" id="info" aria-live="polite">Меняй местами соседние травы, чтобы собрать 3 и больше в ряд.</p>
      <div class="legend" id="legend"></div>
    </main>
    <div class="overlay" id="overlay">
      <div class="modal">
        <h2 id="endTitle"></h2>
        <p id="endText"></p>
        <button class="action" id="again">Сыграть ещё</button>
      </div>
    </div>

    </div>
    </div>
    <script>
    (function(){const button=document.getElementById('herb-toggle'),content=document.getElementById('herb-content');if(!button||button.dataset.bound)return;button.dataset.bound='1';button.addEventListener('click',()=>{const open=content.hidden;content.hidden=!open;button.setAttribute('aria-expanded',String(open));button.textContent=open?'✦ Травяная поляна · Свернуть игру ▴':'✦ Травяная поляна · Открыть игру ▾';})})();
    </script>
    <script>
    (()=>{
    'use strict';
    if(!document.getElementById('herb-forum'))return;
    const N=8;
    const herbs=[
    {name:'Кошачья мята',id:'catmint',tint:'#93d071'},
    {name:'Мак',id:'poppy',tint:'#db685f'},
    {name:'Ромашка',id:'camomile',tint:'#f0dd95'},
    {name:'Можжевельник',id:'juniper',tint:'#6ea8d9'},
    {name:'Щавель',id:'sorrel',tint:'#7fc16a'},
    {name:'Календула',id:'marigold',tint:'#efad4d'}
    ];
    const el=id=>document.getElementById(id),boardEl=el('board');
    const pause=ms=>new Promise(r=>setTimeout(r,ms));
    const idx=(r,c)=>r*N+c,row=i=>Math.floor(i/N),col=i=>i%N;
    const adjacent=(a,b)=>Math.abs(row(a)-row(b))+Math.abs(col(a)-col(b))===1;
    const random=()=>Math.floor(Math.random()*herbs.length);
    let nextId=0,board=[],score=0,moves=26,selected=null,busy=false,ended=false;
    let hintTimer=null,session=0,goals=[],level=1,lastWin=false;
    try{level=Math.max(1,Math.min(500,Number(localStorage.getItem('herbMatchLevel')||1)))}catch{}
    function levelSettings(l){
    // Modest ramp: 26 to 20 moves, no further move reductions.
    const moves=Math.max(20,26-Math.floor((l-1)/3));
    // Targets do grow, but remain bounded in relation to moves. Rotating objectives
    // avoids requiring large amounts of a rare color in a single game.
    const ramp=Math.min(6,Math.floor((l-1)/2));
    const quantities=[7+ramp,6+ramp,5+ramp];
    const cap=Math.floor(moves*.60);
    return {moves,quantities:quantities.map(n=>Math.min(n,cap)),label:l<4?'Лесная опушка':l<9?'Глубокий лес':l<16?'Сложный сбор':'Мастер целительства'};
    }
    let best=0;try{best=Number(localStorage.getItem('herbMatchBest')||0)}catch{}
    const piece=(type,special=null)=>({id:++nextId,type,special});
    const symbol=h=>`<svg viewBox="5 3 54 54" aria-hidden="true"><use href="#herb-${h.id}"></use></svg>`;
    el('legend').innerHTML=herbs.map(h=>`<div class="legend-item">${symbol(h)}<span>${h.name}</span></div>`).join('');
    function say(t){el('info').textContent=t}
    function update(){
    el('score').textContent=score;el('moves').textContent=moves;el('best').textContent=best;el('level').textContent=level;el('levelNote').textContent=levelSettings(level).label;
    el('goals').innerHTML=goals.map(g=>`<div class="goal-chip ${g.left===0?'done':''}">${symbol(herbs[g.type])}<span>${herbs[g.type].name}: <b>${g.left===0?'✓':g.left}</b></span></div>`).join('');
    }
    function scan(b){
    const groups=[];const get=i=>b[i]?.type;
    for(let r=0;r<N;r++){let c=0;while(c<N){let e=c+1;while(e<N&&get(idx(r,c))!=null&&get(idx(r,e))===get(idx(r,c)))e++;if(get(idx(r,c))!=null&&e-c>=3)groups.push({line:Array.from({length:e-c},(_,k)=>idx(r,c+k)),dir:'row'});c=e}}
    for(let c=0;c<N;c++){let r=0;while(r<N){let e=r+1;while(e<N&&get(idx(r,c))!=null&&get(idx(e,c))===get(idx(r,c)))e++;if(get(idx(r,c))!=null&&e-r>=3)groups.push({line:Array.from({length:e-r},(_,k)=>idx(r+k,c)),dir:'col'});r=e}}
    // 2x2 squares produce an exploding herb even if they do not form a line.
    const squares=[];for(let r=0;r<N-1;r++)for(let c=0;c<N-1;c++){const sq=[idx(r,c),idx(r+1,c),idx(r,c+1),idx(r+1,c+1)];if(get(sq[0])!=null&&sq.every(i=>get(i)===get(sq[0])))squares.push(sq)}
    return {groups,squares};
    }
    function canMove(a,b){
    if(board[a]?.special==='bomb'||board[b]?.special==='bomb')return true;
    [board[a],board[b]]=[board[b],board[a]];
    const s=scan(board);const ok=s.groups.length>0||s.squares.length>0;
    [board[a],board[b]]=[board[b],board[a]];
    return ok;
    }
    function validMoves(){
    const result=[];for(let i=0;i<N*N;i++)for(const j of [i+1,i+N])if(j<N*N&&adjacent(i,j)&&canMove(i,j))result.push([i,j]);
    return result;
    }
    function fresh(){
    for(let attempt=0;attempt<200;attempt++){
    board=Array(N*N).fill(null);
    for(let i=0;i<board.length;i++){
    const choices=herbs.map((_,k)=>k).filter(t=>!(col(i)>=2&&board[i-1]?.type===t&&board[i-2]?.type===t)&&!(row(i)>=2&&board[i-N]?.type===t&&board[i-2*N]?.type===t)&&!(row(i)>=1&&col(i)>=1&&board[i-1]?.type===t&&board[i-N]?.type===t&&board[i-N-1]?.type===t));
    board[i]=piece(choices[Math.floor(Math.random()*choices.length)]);
    }
    if(validMoves().length)return;
    }
    }
    function draw({animate=true}={}){
    const previous=new Map();
    if(animate)for(const node of boardEl.children)previous.set(Number(node.dataset.id),node.getBoundingClientRect());
    const fragment=document.createDocumentFragment();
    board.forEach((p,i)=>{
    const node=document.createElement('button');node.type='button';node.className='tile'+(selected===i?' selected':'')+(p?.special?' '+p.special:'');
    node.dataset.i=i;node.dataset.id=p?.id||0;
    node.setAttribute('aria-label',`Ряд ${row(i)+1}, столбец ${col(i)+1}: ${p?(p.special?p.special+' ':'')+(p.special==='bomb'?'Цветная бомба':herbs[p.type].name):'пусто'}`);
    if(p){
    node.style.setProperty('--tileTint',p.type==null?'#a98be4':herbs[p.type].tint);
    node.innerHTML=p.special==='bomb'?'<span class="bomb-core" aria-hidden="true"></span>':`<span class="herb-wrap" aria-hidden="true">${symbol(herbs[p.type])}</span>${p.special?'<span class="special-mark" aria-hidden="true">'+(p.special==='striped'?'↔':'✦')+'</span>':''}`;
    }
    fragment.append(node);
    });
    boardEl.replaceChildren(fragment);
    if(!animate)return;
    for(const node of boardEl.children){
    const p=previous.get(Number(node.dataset.id));
    if(p&&Number(node.dataset.id)>0){
    const now=node.getBoundingClientRect(),dx=p.left-now.left,dy=p.top-now.top;
    if(Math.abs(dx)+Math.abs(dy)>1)node.animate([{transform:`translate(${dx}px,${dy}px)`,zIndex:4},{transform:'translate(0,0)',zIndex:1}],{duration:300,easing:'cubic-bezier(.22,.8,.24,1)'});
    }else if(Number(node.dataset.id)>0){node.classList.add('spawn');node.addEventListener('animationend',()=>node.classList.remove('spawn'),{once:true})}
    }
    }
    function swap(a,b){[board[a],board[b]]=[board[b],board[a]]}
    function addScore(amount){score+=amount;if(score>best){best=score;try{localStorage.setItem('herbMatchBest',String(best))}catch{}}}
    function refill(){
    for(let c=0;c<N;c++){let target=N-1;for(let r=N-1;r>=0;r--)if(board[idx(r,c)]!==null){board[idx(target,c)]=board[idx(r,c)];if(target!==r)board[idx(r,c)]=null;target--}
    while(target>=0)board[idx(target--,c)]=piece(random());
    }
    }
    function chosenSpecial(s,anchor){
    // Priorities: five-line color bomb, 4-line stripe, 2x2 burst.
    const options=[];
    for(const g of s.groups)if(g.line.length>=5)options.push({indices:g.line,special:'bomb',power:30});
    for(const g of s.groups)if(g.line.length===4)options.push({indices:g.line,special:'striped',power:20});
    for(const sq of s.squares)options.push({indices:sq,special:'burst',power:10});
    options.sort((a,b)=>b.power-a.power);
    if(!options.length)return null;
    const o=options[0];
    const position=o.indices.includes(anchor)?anchor:o.indices[Math.floor(o.indices.length/2)];
    return {...o,position};
    }
    function effectIndices(i,p,remove){
    if(p.special==='striped'){
      for(let c=0;c<N;c++)remove.add(idx(row(i),c));
      for(let r=0;r<N;r++)remove.add(idx(r,col(i)));
    }else if(p.special==='burst'){
      for(let r=Math.max(0,row(i)-1);r<=Math.min(N-1,row(i)+1);r++)for(let c=Math.max(0,col(i)-1);c<=Math.min(N-1,col(i)+1);c++)remove.add(idx(r,c));
    }
    }
    async function resolve(anchor=-1,forced=null,run=session){
    let chain=0;
    while(run===session){
      const s=scan(board);
      if(!s.groups.length&&!s.squares.length&&!forced?.size)break;
      chain++;
      const remove=new Set(forced||[]);
      forced=null;
      for(const g of s.groups)g.line.forEach(i=>remove.add(i));
      for(const sq of s.squares)sq.forEach(i=>remove.add(i));
      const make=chosenSpecial(s,anchor);
      const protectedIndex=make?.position;
      // A newly created special piece is kept in the board.
      if(make&&board[protectedIndex]){
       board[protectedIndex]={...board[protectedIndex],special:make.special,type:make.special==='bomb'?null:board[protectedIndex].type};
       remove.delete(protectedIndex);
      }
      const activated=new Set();
      let expand=true;
      while(expand){
       expand=false;
       for(const i of [...remove]){
        const p=board[i];
        if(!p||!p.special||p.special==='bomb'||activated.has(p.id))continue;
        activated.add(p.id);const count=remove.size;effectIndices(i,p,remove);
        if(remove.size>count)expand=true;
       }
      }
      const gathered=new Map();
      for(const i of remove)if(board[i]?.type!=null)gathered.set(board[i].type,(gathered.get(board[i].type)||0)+1);
      for(const g of goals)g.left=Math.max(0,g.left-(gathered.get(g.type)||0));
      addScore(remove.size*60*chain+(make?150:0));
      say(make?`Создан бонус: ${make.special==='bomb'?'цветная бомба':make.special==='striped'?'полосатая трава':'взрывная трава'}!`:chain>1?`Каскад ×${chain}! Собрано ${remove.size} трав.`:`Собрано ${remove.size} трав!`);
      update();draw();
      await pause(160);if(run!==session)return;
      for(const i of remove){const node=boardEl.children[i];if(node)node.classList.add('disappear')}
      await pause(250);if(run!==session)return;
      for(const i of remove)board[i]=null;
      refill();draw();await pause(330);
      anchor=-1;
    }
    }
    async function activateBomb(a,b,run){
    const first=board[a],second=board[b],remove=new Set([a,b]);
    if(first.special==='bomb'&&second.special==='bomb'){
      for(let i=0;i<N*N;i++)remove.add(i);
    }else{
      const other=first.special==='bomb'?second:first;
      if(other.type!=null)for(let i=0;i<N*N;i++)if(board[i]?.type===other.type)remove.add(i);
    }
    // Bomb interactions with other specials also trigger their abilities.
    const expanded=new Set();
    for(const i of [...remove])if(board[i]?.special&&board[i].special!=='bomb'&&!expanded.has(i)){expanded.add(i);effectIndices(i,board[i],remove)}
    await resolve(-1,remove,run);
    }
    function finish(){
    ended=true;const won=goals.every(g=>g.left===0);lastWin=won;
    el('endTitle').textContent=won?`Уровень ${level} пройден!`:`Уровень ${level}: не хватило трав`;
    el('endText').textContent=won?`Целитель получил все травы! Результат: ${score} очков. Следующий уровень будет немного сложнее.`:`Набрано ${score} очков. Осталось собрать: ${goals.filter(g=>g.left).map(g=>herbs[g.type].name+' ×'+g.left).join(', ')}. Попробуй ещё раз: каждый уровень можно пройти без покупок.`;
    el('again').textContent=won?'Следующий уровень':'Повторить уровень';
    el('overlay').classList.add('show');
    }
    async function play(a,b){
    if(busy||ended||!adjacent(a,b))return;
    busy=true;selected=null;const run=session;
    const specialBomb=board[a]?.special==='bomb'||board[b]?.special==='bomb';
    swap(a,b);draw();await pause(300);
    if(run!==session)return;
    const s=scan(board);
    if(!specialBomb&&!s.groups.length&&!s.squares.length){
      swap(a,b);draw();say('Нужно собрать ряд из 3 трав или квадрат 2×2.');busy=false;return;
    }
    moves--;update();
    if(specialBomb)await activateBomb(a,b,run);else await resolve(b,null,run);
    if(run!==session)return;
    if(goals.every(g=>g.left===0)||moves<=0){finish();busy=false;return}
    if(!validMoves().length){say('Ходов нет — перемешиваем поляну.');await pause(300);if(run!==session)return;shuffle()}
    busy=false;
    }
    function shuffle(){
    const pieces=board.slice();
    for(let t=0;t<300;t++){
      for(let i=pieces.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[pieces[i],pieces[j]]=[pieces[j],pieces[i]]}
      board=pieces.slice();const s=scan(board);if(!s.groups.length&&!s.squares.length&&validMoves().length){draw();return}
    }
    fresh();draw();
    }
    function choose(i){
    if(busy||ended)return;
    if(selected===null){selected=i;draw({animate:false});return}
    if(selected===i){selected=null;draw({animate:false});return}
    const a=selected;
    if(adjacent(a,i))play(a,i);else{selected=i;draw({animate:false})}
    }
    let suppressClick=false,start=null;
    boardEl.addEventListener('click',e=>{if(suppressClick){suppressClick=false;return}const node=e.target.closest('.tile');if(node)choose(Number(node.dataset.i))});
    boardEl.addEventListener('pointerdown',e=>{const node=e.target.closest('.tile');if(node)start={i:Number(node.dataset.i),x:e.clientX,y:e.clientY}});
    boardEl.addEventListener('pointerup',e=>{
    if(!start||busy||ended)return;
    const dx=e.clientX-start.x,dy=e.clientY-start.y;
    if(Math.max(Math.abs(dx),Math.abs(dy))>22){
      const r=row(start.i)+(Math.abs(dy)>Math.abs(dx)?Math.sign(dy):0);
      const c=col(start.i)+(Math.abs(dx)>=Math.abs(dy)?Math.sign(dx):0);
      if(r>=0&&r<N&&c>=0&&c<N){suppressClick=true;play(start.i,idx(r,c))}
    }
    start=null;
    });
    boardEl.addEventListener('pointercancel',()=>start=null);
    el('hint').addEventListener('click',()=>{
    if(busy||ended)return;
    const list=validMoves();if(!list.length)return;
    const pair=list[Math.floor(Math.random()*list.length)];
    boardEl.querySelectorAll('.hint').forEach(n=>n.classList.remove('hint'));
    pair.forEach(i=>boardEl.children[i].classList.add('hint'));
    say('Перемести одну подсвеченную траву на место другой.');
    clearTimeout(hintTimer);hintTimer=setTimeout(()=>boardEl.querySelectorAll('.hint').forEach(n=>n.classList.remove('hint')),2200);
    });
    function reset(){
    session++;clearTimeout(hintTimer);score=0;moves=levelSettings(level).moves;selected=null;busy=false;ended=false;lastWin=false;
    el('overlay').classList.remove('show');
    const chosen=herbs.map((_,i)=>i).sort(()=>Math.random()-.5).slice(0,3);
    const settings=levelSettings(level);
    goals=chosen.map((type,i)=>({type,left:settings.quantities[i]}));
    fresh();draw({animate:false});update();
    say('4 в ряд — полосатая, квадрат 2×2 — взрывная, 5 в ряд — цветная бомба.');
    }
    el('restart').addEventListener('click',reset);
    el('again').addEventListener('click',()=>{
    if(lastWin){level++;try{localStorage.setItem('herbMatchLevel',String(level))}catch{}}
    reset();
    });
    reset();
    })();
    </script>
    [/html]

    после обновления страницы прогресс сохраняется!! но как будто не очень сложно все еще, он каждые 3 уровня усложняет, уменьшая количество ходов. надо балансить это дело и наверное делать меньше экран, чтоб помещался хд пишите фидбэк, я и мой нейросетевой друг поправим это дело

    +8

    56

    Внезапно мозг сказал, что я забыла в каком времени пишу посты.

    +1

    57

    Зайцезвёзд, круто играется!!

    +1

    58

    https://upforme.ru/uploads/001c/55/b9/18/t273595.png
    йопиии

    +2

    59

    https://upforme.ru/uploads/001b/45/b2/2/187922.gif

    0

    60

    Я залипла до 14-го уровня, но не ощущаю, что идёт усложнение. Или, может, за это время я просто поднаторела уже и к картинкам привыкла, поэтому легче играется. Очень клёво!!!!!!!!! И мозг разгружает, потому что ходов относительно много, а подсказки бесплатные

    +1


    Вы здесь » Warrior Cats: The Voice of Memories » Общение » флуд №108 в честь змейки