import React from 'react';
import DocIcon from './docsIcons';

/**
 * docsData.jsx — контент вики редактора Рублокс (разделы A-J).
 *
 * Структура: DOCS = массив глав. Каждая глава —
 *   { id, icon, title, summary, sections: [{ id, title, body }] }
 *  - icon    — имя SVG-иконки из docsIcons.jsx (НЕ эмодзи).
 *  - summary — короткое описание для карточки на главной вики.
 *
 * Хелперы для оформления:
 *  - <Code>      — код-блок (тёмный, моноширинный)
 *  - <ScriptKind kind="global|object" on="...">  — плашка «куда писать скрипт»
 *  - <Step n="1"> — шаг инструкции
 *  - <Note>      — жёлтая плашка-подсказка
 *  - <Try>       — зелёная плашка «попробуй сам»
 *
 * Контент написан для детей 5 класса+. Каждый пример — рабочий код,
 * который можно скопировать в свою игру. Эмодзи в UI не используются —
 * только SVG-иконки (см. docsIcons.jsx).
 */

// ── Код-блок ──────────────────────────────────────────────────────
export const Code = ({ children }) => (
    <pre className="docCode"><code>{children}</code></pre>
);

// ── Плашка «куда писать скрипт» ───────────────────────────────────
// kind="global"  — глобальный скрипт (создаётся в категории «Скрипты»)
// kind="object"  — скрипт привязан к объекту (передай on="название объекта")
export const ScriptKind = ({ kind, on }) => {
    if (kind === 'object') {
        return (
            <div className="docScriptKind docScriptKind--object">
                <span className="docScriptKind__ico"><DocIcon name="pin" size={18} /></span>
                <span>
                    <b>Куда писать:</b> этот скрипт нужно <b>повесить на объект</b>
                    {on ? <> — на <b>{on}</b></> : null}. Выдели объект на сцене
                    и создай скрипт прямо на нём. Тогда внутри скрипта работает
                    слово <code>game.self</code> — это и есть твой объект.
                </span>
            </div>
        );
    }
    return (
        <div className="docScriptKind docScriptKind--global">
            <span className="docScriptKind__ico"><DocIcon name="globeIcon" size={18} /></span>
            <span>
                <b>Куда писать:</b> это <b>глобальный скрипт</b>. Создай его
                в иерархии в категории <b>Скрипты</b> (кнопка «+»). Он не привязан
                ни к какому объекту и запускается один раз при старте игры.
            </span>
        </div>
    );
};

// ── Шаг инструкции ────────────────────────────────────────────────
export const Step = ({ n, children }) => (
    <div className="docStep">
        <span className="docStep__num">{n}</span>
        <div className="docStep__body">{children}</div>
    </div>
);

// ── Жёлтая плашка-подсказка ───────────────────────────────────────
export const Note = ({ children }) => (
    <div className="docNote">
        <span className="docNote__ico"><DocIcon name="lightbulb" size={17} /></span>
        <div>{children}</div>
    </div>
);

// ── Зелёная плашка «попробуй сам» ─────────────────────────────────
export const Try = ({ children }) => (
    <div className="docTry">
        <span className="docTry__ico"><DocIcon name="target" size={17} /></span>
        <div>
            <b>Попробуй сам:</b> {children}
        </div>
    </div>
);

// ── Скриншот интерфейса с подписью ────────────────────────────────
// Версия вики-ассетов (cache-buster). Бампать при добавлении/замене картинок
// в public/wiki/ — иначе у юзеров, открывавших статью ДО заливки файла,
// браузер кэширует битый SPA-fallback (HTML вместо PNG) и Ctrl+Shift+R не
// помогает (инцидент 2026-06-03 с guide-taxisim). Новый ?v=N = новый URL.
export const WIKI_ASSET_V = 4;

/** URL вики-картинки с версией для обхода кэша. */
export const wikiUrl = (name) => `/wiki/${name}?v=${WIKI_ASSET_V}`;

// src — имя файла из public/wiki/, caption — подпись под картинкой.
// wide — для широких скринов (обзор, лента): растянуть на всю ширину.
export const Shot = ({ src, caption, wide }) => (
    <figure className={'docShot' + (wide ? ' docShot--wide' : '')}>
        <img src={wikiUrl(src)} alt={caption || ''} loading="lazy" />
        {caption && <figcaption>{caption}</figcaption>}
    </figure>
);

// ══════════════════════════════════════════════════════════════════
// DOCS — разделы вики A-J
// ══════════════════════════════════════════════════════════════════

export const DOCS = [
    // ════════════════════════════════════════════════════
    // РАЗДЕЛ A — ОСНОВЫ
    // ════════════════════════════════════════════════════
    {
        id: 'basics',
        icon: 'rocket',
        title: 'Основы',
        summary: 'С чего начать: интерфейс редактора, инструменты, первая игра за 5 минут.',
        sections: [
            {
                id: 'what-is-rublox',
                title: 'A1. Что такое Рублокс и редактор игр',
                body: (
                    <>
                        <p>
                            <b>Рублокс</b> — это платформа, где можно играть в 3D-игры
                            и создавать свои собственные. Всё работает прямо в браузере:
                            ничего скачивать и устанавливать не нужно.
                        </p>
                        <p>
                            <b>Редактор игр</b> (его ещё называют Studio) — это место,
                            где ты строишь игру. Ты ставишь блоки и модели, рисуешь
                            кнопки, пишешь скрипты — а потом нажимаешь «Играть»
                            и сразу проверяешь, что получилось.
                        </p>
                        <p>В Рублоксе можно сделать почти любую игру:</p>
                        <ul>
                            <li>паркур и платформеры — прыгай по платформам;</li>
                            <li>гонки — мчись к финишу на время;</li>
                            <li>стрелялки и арены — сражайся с врагами;</li>
                            <li>головоломки и квесты — решай загадки;</li>
                            <li>выживалки и целые RPG с героями и заданиями.</li>
                        </ul>
                        <p>
                            <b>Как устроена эта вика.</b> Разделы A-C научат строить
                            мир и интерфейс. Разделы D-G — писать скрипты (код, который
                            оживляет игру). Раздел H — справочник всех команд. Раздел I —
                            словарик непонятных слов. Раздел J — что делать, если
                            что-то сломалось. Раздел K — 50 готовых игр-уроков.
                        </p>
                        <Note>
                            Не нужно читать всё подряд. Пройди раздел «Основы»,
                            а дальше открывай то, что нужно прямо сейчас.
                        </Note>
                    </>
                ),
            },
            {
                id: 'editor-interface',
                title: 'A2. Интерфейс редактора',
                body: (
                    <>
                        <p>
                            Когда ты открываешь игру в редакторе, экран делится
                            на части. Разберём каждую:
                        </p>
                        <Shot src="a2-overview.png" wide
                              caption="Четыре главные зоны редактора" />
                        <ul>
                            <li>
                                <b>1 — Шапка сверху</b> — название игры и кнопки:
                                <kbd className="kbd">Настройки</kbd>,
                                <kbd className="kbd">Сохранить</kbd>,
                                <kbd className="kbd">Играть</kbd>,
                                <kbd className="kbd">Опубликовать</kbd>.
                            </li>
                            <li>
                                <b>2 — Лента инструментов</b> под шапкой — вкладки
                                <i> Главная / Модель / Игра / Вид</i>. На каждой вкладке
                                свои кнопки и инструменты.
                            </li>
                            <li>
                                <b>3 — 3D-сцена (вьюпорт)</b> — твой игровой мир
                                в центре экрана. Тут ты всё и строишь.
                            </li>
                            <li>
                                <b>4 — Правая панель</b> — сверху <i>Иерархия</i> (список
                                всех объектов), снизу <i>Инспектор</i> (свойства того
                                объекта, который ты выделил мышкой).
                            </li>
                        </ul>
                        <p>
                            Когда ты выбираешь инструмент «Блок» или «Примитив»,
                            слева открывается ещё одна <b>палитра</b> — там лежат
                            фигуры, которые можно ставить на сцену.
                        </p>
                        <Shot src="a2-topbar.png"
                              caption="Шапка: название игры и главные кнопки" />
                        <Shot src="a2-ribbon.png" wide
                              caption="Лента инструментов — все инструменты создания" />
                        <p><b>Как двигать камеру в редакторе:</b></p>
                        <table className="docTable">
                            <tbody>
                                <tr><td>Правая кнопка мыши + движение</td><td>осмотреться по сторонам</td></tr>
                                <tr><td><kbd className="kbd">W</kbd><kbd className="kbd">A</kbd><kbd className="kbd">S</kbd><kbd className="kbd">D</kbd></td><td>лететь вперёд / влево / назад / вправо</td></tr>
                                <tr><td>Колесо мыши</td><td>приблизить / отдалить</td></tr>
                            </tbody>
                        </table>
                        <Note>
                            Камера редактора и камера игрока — это <b>разные</b> камеры.
                            То, как ты летаешь по сцене сейчас, не влияет на то, как
                            будет видеть мир игрок.
                        </Note>
                    </>
                ),
            },
            {
                id: 'first-game-5min',
                title: 'A3. Первая игра за 5 минут',
                body: (
                    <>
                        <p>
                            Соберём самую простую игру — площадку, по которой можно
                            ходить. Делай по шагам.
                        </p>
                        <Step n="1">
                            Открой редактор и создай <b>новую игру</b>
                            (или выбери пустой шаблон).
                        </Step>
                        <Step n="2">
                            На вкладке <b>Главная</b> выбери инструмент
                            <kbd className="kbd">Блок</kbd>. В левой палитре кликни
                            на блок травы — он станет выбранным.
                        </Step>
                        <Step n="3">
                            Кликай по сцене — блоки будут вставать один за другим.
                            Собери небольшую площадку примерно 6×6 блоков.
                        </Step>
                        <Step n="4">
                            Перейди на вкладку <b>Игра</b> и выбери
                            <kbd className="kbd">Ставить спавн</kbd>. Кликни
                            на площадку — там появится точка, где игрок начнёт игру.
                        </Step>
                        <Step n="5">
                            Нажми <kbd className="kbd">Играть</kbd> в шапке. Ты
                            окажешься на своей площадке и сможешь по ней ходить!
                        </Step>
                        <Step n="6">
                            Нажми <kbd className="kbd">Esc</kbd>, чтобы вернуться
                            в редактор, и <kbd className="kbd">Сохранить</kbd>.
                        </Step>
                        <p>
                            Поздравляем — это уже работающая игра. Дальше ты добавишь
                            в неё препятствия, врагов, монетки и логику.
                        </p>
                        <Try>
                            добавь по краям площадки стены из блоков, чтобы нельзя
                            было упасть. И поставь в центре несколько блоков-ступенек.
                        </Try>
                    </>
                ),
            },
            {
                id: 'creation-tools',
                title: 'A4. Инструменты: блок, примитив, модель, ландшафт',
                body: (
                    <>
                        <p>На вкладке <b>Главная</b> есть инструменты создания:</p>
                        <Shot src="a4-tools.png"
                              caption="Инструменты создания: Блок, Примитив, Модель" />
                        <ul>
                            <li>
                                <b>Блок</b> — ставит кубический блок (трава, камень,
                                дерево...). Блоки ровно встают по сетке — из них удобно
                                строить дома и стены, как из кубиков Лего.
                            </li>
                            <li>
                                <b>Примитив</b> — простая фигура: куб, сфера, цилиндр,
                                конус, плоскость, тор, клин. У примитива можно свободно
                                менять размер по каждой оси и красить в любой цвет.
                            </li>
                            <li>
                                <b>Модель</b> — готовая красивая 3D-модель из библиотеки
                                (дерево, бочка, машина, оружие). Можно загружать и свои
                                модели в формате <code>.glb</code>.
                            </li>
                            <li>
                                <b>Ландшафт</b> — инструмент лепки рельефа: холмы, горы,
                                пещеры. Об этом — раздел B4.
                            </li>
                            <li>
                                <b>Стереть</b> — удаляет блок или объект под курсором.
                            </li>
                        </ul>
                        <p>
                            Когда выбираешь «Блок» или «Примитив», слева открывается
                            <b> палитра</b> — выбери в ней фигуру, а потом кликай
                            по сцене, чтобы её поставить.
                        </p>
                        <Shot src="a4-palette.png"
                              caption="Палитра примитивов — выбранная фигура подсвечена синим" />
                        <p>
                            <b>Шаг привязки</b> (1.0 / 0.5 / 0.25 / Выкл) — задаёт,
                            насколько мелко объект «прилипает» к сетке, когда ты его
                            двигаешь. Шаг 1.0 — объект двигается крупными шагами,
                            ровно по клеткам. Маленький шаг 0.25 — точнее, но дольше.
                        </p>
                        <Shot src="a4-snap.png"
                              caption="Переключатель шага привязки" />
                        <Note>
                            Чем отличаются блок и примитив-куб? Блок всегда одного
                            размера и быстро ставится сеткой — он для стройки.
                            Примитив-куб можно растянуть в длинную платформу или
                            тонкую стенку — он для геймплея.
                        </Note>
                    </>
                ),
            },
            {
                id: 'gizmo',
                title: 'A5. Гизмо-манипуляторы: двигать, вращать, масштаб',
                body: (
                    <>
                        <p>
                            <b>Гизмо</b> — это цветные стрелки и кольца, которые
                            появляются на выделенном объекте. Они помогают точно
                            его двигать, поворачивать и менять размер.
                        </p>
                        <p>
                            Режим гизмо выбирается в ленте инструментов — группа
                            «Манипуляторы»:
                        </p>
                        <Shot src="a5-gizmo-tools.png"
                              caption="Кнопки гизмо: Выделить, Двигать, Вращать, Масштаб" />
                        <table className="docTable">
                            <tbody>
                                <tr><td><b>Выделить</b></td><td>обычный режим, клик выбирает объект</td></tr>
                                <tr><td><b>Двигать</b></td><td>три стрелки X / Y / Z — тяни, объект едет по оси</td></tr>
                                <tr><td><b>Вращать</b></td><td>три кольца — тяни, объект поворачивается</td></tr>
                                <tr><td><b>Масштаб</b></td><td>кубики на осях — тяни, объект растягивается</td></tr>
                            </tbody>
                        </table>
                        <p>
                            Вот как выглядит гизмо «Двигать» на выделенном кубе —
                            три цветные стрелки:
                        </p>
                        <Shot src="a5-gizmo.png"
                              caption="Гизмо «Двигать»: стрелки X (красная), Y (зелёная), Z (синяя)" />
                        <p>
                            Оси всегда одни и те же и покрашены одинаково:
                        </p>
                        <ul>
                            <li><b>X</b> (красная) — влево / вправо;</li>
                            <li><b>Y</b> (зелёная) — вверх / вниз;</li>
                            <li><b>Z</b> (синяя) — вперёд / назад.</li>
                        </ul>
                        <Note>
                            Эти же буквы X, Y, Z ты увидишь в скриптах. Когда команда
                            пишет <code>{`{ x: 5, y: 2, z: 0 }`}</code> — это точка
                            в мире: 5 вправо, 2 вверх, 0 вперёд.
                        </Note>
                    </>
                ),
            },
            {
                id: 'hierarchy',
                title: 'A6. Иерархия объектов и папки',
                body: (
                    <>
                        <p>
                            <b>Иерархия</b> — это список всех объектов твоей игры
                            в правой панели. Когда сцена большая, найти нужный куб
                            мышкой трудно — а в списке он всегда под рукой.
                        </p>
                        <Shot src="a6-hierarchy.png"
                              caption="Правая панель: сверху иерархия объектов, снизу инспектор свойств" />
                        <p>Объекты сгруппированы по категориям:</p>
                        <ul>
                            <li><b>Сцена</b> — точка спавна, окружение, свет;</li>
                            <li><b>Игрок</b> — скин персонажа;</li>
                            <li><b>Интерфейс</b> — GUI-элементы (кнопки, надписи);</li>
                            <li><b>Скрипты</b> — твой код.</li>
                        </ul>
                        <p>
                            <b>Имя объекта.</b> У каждого объекта есть имя — его видно
                            в иерархии и можно изменить в инспекторе. Имена очень важны
                            для скриптов: команда <code>game.scene.findOne('Дверь')</code>
                            находит объект <b>по имени</b>. Давай объектам понятные
                            имена: «Дверь», «Монетка1», «Босс».
                        </p>
                        <p>
                            <b>Папки.</b> Объекты можно складывать в свои папки —
                            например, папка «Уровень 1», папка «Враги». Это как
                            наводить порядок в шкафу: всё на своих полках. Двойной
                            клик по объекту в списке — камера прилетит прямо к нему.
                        </p>
                    </>
                ),
            },
            {
                id: 'hotkeys',
                title: 'A7. Горячие клавиши',
                body: (
                    <>
                        <p>Горячие клавиши экономят кучу времени:</p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><kbd className="kbd">Ctrl</kbd>+<kbd className="kbd">S</kbd></td><td>Сохранить игру</td></tr>
                                <tr><td><kbd className="kbd">Ctrl</kbd>+<kbd className="kbd">Z</kbd></td><td>Отменить последнее действие</td></tr>
                                <tr><td><kbd className="kbd">Ctrl</kbd>+<kbd className="kbd">D</kbd></td><td>Дублировать выделенный объект</td></tr>
                                <tr><td><kbd className="kbd">Del</kbd></td><td>Удалить выделенное</td></tr>
                                <tr><td><kbd className="kbd">R</kbd></td><td>Повернуть объект на 90°</td></tr>
                                <tr><td><kbd className="kbd">Esc</kbd></td><td>Снять выделение / выйти из режима</td></tr>
                                <tr><td><kbd className="kbd">F</kbd></td><td>Навести камеру на выделенное</td></tr>
                            </tbody>
                        </table>
                        <Note>
                            Самая полезная привычка — почаще жать
                            <kbd className="kbd">Ctrl</kbd>+<kbd className="kbd">S</kbd>.
                            Сохраняться нужно не «когда закончил», а каждые пару минут.
                        </Note>
                    </>
                ),
            },
            {
                id: 'play-mode',
                title: 'A8. Режим игры: HP, смерть, респаун',
                body: (
                    <>
                        <p>
                            Кнопка <kbd className="kbd">Запустить</kbd> в правой части
                            ленты запускает игру. Сцена «оживает»: включается физика,
                            начинают работать скрипты, появляется HUD (счётчики поверх
                            экрана). Чтобы остановить игру — кнопка
                            <kbd className="kbd">Стоп</kbd> или клавиша
                            <kbd className="kbd">Esc</kbd>.
                        </p>
                        <Shot src="a8-play.png"
                              caption="Кнопка «Запустить» — проверить игру; «Стоп» — вернуться в редактор" />
                        <p><b>Управление в игре:</b></p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><kbd className="kbd">W</kbd><kbd className="kbd">A</kbd><kbd className="kbd">S</kbd><kbd className="kbd">D</kbd></td><td>Идти</td></tr>
                                <tr><td><kbd className="kbd">Space</kbd></td><td>Прыжок</td></tr>
                                <tr><td><kbd className="kbd">Shift</kbd></td><td>Бег</td></tr>
                                <tr><td>Мышь</td><td>Поворот камеры</td></tr>
                                <tr><td>ЛКМ</td><td>Атака / стрельба</td></tr>
                                <tr><td><kbd className="kbd">E</kbd></td><td>Взаимодействовать</td></tr>
                                <tr><td><kbd className="kbd">1</kbd>…<kbd className="kbd">5</kbd></td><td>Слот инвентаря</td></tr>
                                <tr><td><kbd className="kbd">C</kbd></td><td>1-е / 3-е лицо</td></tr>
                            </tbody>
                        </table>
                        <p>
                            <b>HP (здоровье)</b> игрока видно в левом верхнем углу.
                            Когда игрок получает урон, полоска краснеет. Если HP падает
                            до нуля — игрок «умирает» и через пару секунд
                            <b> воскресает (респаун)</b> на точке спавна с полным
                            здоровьем.
                        </p>
                        <p>
                            Всем этим можно управлять из скриптов: наносить урон,
                            лечить, ставить чекпоинты. Об этом — раздел F1.
                        </p>
                    </>
                ),
            },
            {
                id: 'save-publish',
                title: 'A9. Сохранение и публикация',
                body: (
                    <>
                        <p>
                            <b>Сохранение</b> — кнопка <kbd className="kbd">Сохранить</kbd>
                            или <kbd className="kbd">Ctrl</kbd>+<kbd className="kbd">S</kbd>.
                            Игра автоматически сохраняется и сама время от времени,
                            но лучше не лениться и сохранять руками.
                        </p>
                        <p>
                            <b>Публикация</b> — когда игра готова, нажми
                            <kbd className="kbd">Опубликовать</kbd>. Выбери
                            возрастной рейтинг (6+, 12+, 16+, 18+) и куда отправить:
                        </p>
                        <ul>
                            <li>
                                <b>В главную ленту</b> — игру увидят все ученики.
                                Модерация строже.
                            </li>
                            <li>
                                <b>Только в профиле</b> — игра доступна по ссылке
                                и в твоём профиле, но в общей ленте её не будет.
                            </li>
                        </ul>
                        <p>
                            После отправки игру проверит модератор (обычно за 24-48
                            часов). Игра <b>не должна</b> содержать матов, рекламы,
                            чужого контента (модели из Roblox/Minecraft) и жестокости
                            не по возрасту.
                        </p>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ B — ОБЪЕКТЫ СЦЕНЫ
    // ════════════════════════════════════════════════════
    {
        id: 'objects',
        icon: 'cube',
        title: 'Объекты сцены',
        summary: 'Блоки, примитивы, модели, ландшафт, свет, частицы и свойства объектов.',
        sections: [
            {
                id: 'blocks',
                title: 'B1. Блоки и их типы',
                body: (
                    <>
                        <p>
                            <b>Блок</b> — это кубик одного размера. Блоки ровно
                            встают по сетке, и из них удобно строить — как из кубиков
                            Лего. В палитре слева есть разные типы: трава, камень,
                            песок, дерево, кирпич, цветные блоки, блоки со снегом.
                        </p>
                        <p>
                            Чтобы поставить блок — выбери инструмент
                            <kbd className="kbd">Блок</kbd>, кликни нужный тип
                            в палитре и кликай по сцене. Чтобы убрать — инструмент
                            <kbd className="kbd">Стереть</kbd>.
                        </p>
                        <Shot src="b1-blocks.png"
                              caption="Палитра блоков — типы сгруппированы по вкладкам" />
                        <p>
                            У блока в инспекторе можно включить/выключить
                            <i> столкновение</i> (твёрдый он или сквозь него можно
                            пройти) и <i>видимость</i>.
                        </p>
                        <Note>
                            Невидимый блок с включённым столкновением — это уже
                            готовый «невидимый барьер». Игрок в него упрётся,
                            но не увидит. Так делают границы уровня.
                        </Note>
                    </>
                ),
            },
            {
                id: 'primitives',
                title: 'B2. Примитивы',
                body: (
                    <>
                        <p>
                            <b>Примитив</b> — простая 3D-фигура. В отличие от блока,
                            у примитива можно свободно менять размер по каждой оси
                            и красить в любой цвет. Виды:
                        </p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><b>Куб</b></td><td>стены, платформы, ящики</td></tr>
                                <tr><td><b>Сфера</b></td><td>мячи, монетки, планеты</td></tr>
                                <tr><td><b>Цилиндр</b></td><td>колонны, бочки, трубы</td></tr>
                                <tr><td><b>Конус</b></td><td>шипы, ёлки, шляпы</td></tr>
                                <tr><td><b>Плоскость</b></td><td>тонкий лист — пол, экран</td></tr>
                                <tr><td><b>Тор</b></td><td>кольцо (как бублик)</td></tr>
                                <tr><td><b>Клин</b></td><td>наклонная фигура — пандус</td></tr>
                            </tbody>
                        </table>
                        <p>
                            Примитивы — главный «строительный материал» для игр.
                            Из растянутых кубов делают платформы для паркура,
                            из сфер — собираемые монетки, из конусов — смертельные
                            шипы.
                        </p>
                        <Note>
                            Чтобы в скрипте было легко найти примитив — дай ему
                            понятное имя в инспекторе. Например, «Платформа1». Потом
                            скрипт найдёт её командой
                            <code> game.scene.findOne('Платформа1')</code>.
                        </Note>
                    </>
                ),
            },
            {
                id: 'models',
                title: 'B3. Готовые модели и импорт своих',
                body: (
                    <>
                        <p>
                            <b>Модель</b> — готовая красивая 3D-фигура: дерево, камень,
                            бочка, машина, оружие, мебель. Их не нужно строить из
                            кубиков — просто бери из библиотеки и ставь на сцену.
                        </p>
                        <p>
                            Инструмент <kbd className="kbd">Модель</kbd> открывает
                            каталог. Модели разбиты по категориям (природа, город,
                            оружие...).
                        </p>
                        <Shot src="b3-models.png" wide
                              caption="Тулбокс — библиотека готовых 3D-моделей" />
                        <p>
                            <b>Свои модели.</b> Можно загрузить собственную 3D-модель
                            в формате <code>.glb</code>. Такие файлы делают в бесплатных
                            редакторах вроде Blender или берут на сайтах с бесплатными
                            моделями. После загрузки твоя модель появится в палитре
                            рядом с остальными.
                        </p>
                        <Note>
                            Не бери модели из других игр (Roblox, Minecraft) —
                            это чужой контент, игру с ним не пропустит модерация.
                            Бери только бесплатные модели «для свободного использования».
                        </Note>
                    </>
                ),
            },
            {
                id: 'terrain',
                title: 'B4. Ландшафт: воксельный и гладкий',
                body: (
                    <>
                        <p>
                            <b>Ландшафт</b> — это рельеф мира: холмы, горы, ямы, пещеры.
                            В Рублоксе два режима:
                        </p>
                        <ul>
                            <li>
                                <b>Воксельный</b> — рельеф из маленьких кубиков-вокселей.
                                Получается «ступенчатый», как в Minecraft. Удобно
                                рисовать пещеры и обрывы.
                            </li>
                            <li>
                                <b>Гладкий</b> — рельеф из плавных холмов без ступенек.
                                Похоже на настоящую землю.
                            </li>
                        </ul>
                        <p>
                            Инструменты лепки: <i>поднять</i>, <i>опустить</i>,
                            <i> разгладить</i>, <i>покрасить</i>. Есть и кисти-растения —
                            рисуешь по земле, и сразу вырастают деревья и трава.
                        </p>
                        <Note>
                            Если в игре есть гладкий ландшафт, ставь точку спавна
                            прямо на его поверхности. Если спавн окажется ниже земли —
                            игрок при старте провалится. Высоту земли в скрипте можно
                            узнать командой <code>game.scene.surfaceY(x, z)</code>.
                        </Note>
                    </>
                ),
            },
            {
                id: 'spawn-checkpoints',
                title: 'B5. Точка спавна и чекпоинты',
                body: (
                    <>
                        <p>
                            <b>Точка спавна</b> — место, где игрок появляется в начале
                            игры и куда возвращается после смерти. Ставится на вкладке
                            <i> Игра → Ставить спавн</i>. Точка спавна одна.
                        </p>
                        <p>
                            <b>Чекпоинт (контрольная точка)</b> — промежуточное место
                            сохранения в длинных уровнях. Когда игрок дошёл до чекпоинта,
                            при следующей смерти он воскреснет уже там, а не в самом
                            начале.
                        </p>
                        <p>
                            Чекпоинт делают скриптом на флажке-объекте: когда игрок
                            касается флажка, скрипт запоминает это место как новый спавн.
                        </p>
                        <ScriptKind kind="object" on="флажок-чекпоинт" />
                        <Code>{`// Когда игрок коснётся флажка —
// это место станет новой точкой возрождения.
game.self.onTouch(() => {
  // game.self.position — координаты самого флажка
  game.player.setSpawn(game.self.position);
  game.ui.showText('Чекпоинт сохранён!', 1.5);
  game.sound.play('pickup');
});`}</Code>
                        <p>
                            Что тут происходит: <code>onTouch</code> срабатывает,
                            когда игрок дотронулся до флажка. <code>setSpawn</code>
                            запоминает точку возрождения. <code>showText</code>
                            показывает надпись на 1.5 секунды. Готово — игрок
                            не начнёт уровень заново.
                        </p>
                    </>
                ),
            },
            {
                id: 'lamps',
                title: 'B6. Лампы (источники света)',
                body: (
                    <>
                        <p>
                            <b>Лампа</b> — это источник света. Кроме общего солнца,
                            можно поставить точечные лампы, которые освещают всё рядом
                            с собой. Они нужны для пещер, ночных уровней, подсветки
                            важных мест.
                        </p>
                        <p>
                            У лампы настраиваются <b>цвет</b>, <b>яркость</b>
                            и <b>радиус</b> (как далеко достаёт свет). Лампу можно
                            создать и из скрипта:
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Создаём тёплую лампу над сценой
game.scene.spawn('light:point', {
  x: 0, y: 4, z: 0,   // где висит лампа
  color: '#ffdd88',   // тёплый жёлтый свет
  brightness: 2,      // яркость
  range: 12           // радиус освещения
});`}</Code>
                    </>
                ),
            },
            {
                id: 'particles',
                title: 'B7. Эмиттеры частиц',
                body: (
                    <>
                        <p>
                            <b>Частицы</b> — это много маленьких летящих точек:
                            искры, дым, огонь, магия. Объект, который их создаёт,
                            называется <b>эмиттер</b>.
                        </p>
                        <p>
                            Частицы делают игру живой: костёр дымит, при победе летит
                            конфетти, у портала кружится магия. Из скрипта это команда
                            <code> game.scene.spawnParticles</code>:
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Залп конфетти над центром сцены
game.scene.spawnParticles(
  'confetti',              // тип эффекта
  { x: 0, y: 3, z: 0 },    // где появятся частицы
  { duration: 2, count: 3 } // длительность и густота
);`}</Code>
                        <p>
                            Типы эффектов: <code>fire</code> (огонь),
                            <code> smoke</code> (дым), <code>sparks</code> (искры),
                            <code> magic</code> (магия), <code>explosion</code> (взрыв),
                            <code> confetti</code> (конфетти).
                        </p>
                    </>
                ),
            },
            {
                id: 'triggers',
                title: 'B8. Триггеры',
                body: (
                    <>
                        <p>
                            <b>Триггер</b> — невидимая зона, которая что-то запускает,
                            когда игрок в неё входит. Например: игрок зашёл в зону —
                            открылась дверь, заиграла музыка, появился враг.
                        </p>
                        <p><b>Как сделать триггер:</b></p>
                        <Step n="1">
                            Поставь примитив-куб нужного размера — это и будет зона.
                        </Step>
                        <Step n="2">
                            В инспекторе <b>выключи столкновение</b> (чтобы игрок
                            проходил сквозь) и можно выключить <b>видимость</b>
                            (чтобы зону не было видно).
                        </Step>
                        <Step n="3">
                            Повесь на этот куб скрипт, который ловит касание игрока:
                        </Step>
                        <ScriptKind kind="object" on="куб-триггер" />
                        <Code>{`// Игрок вошёл в зону — показываем надпись
game.self.onTouch(() => {
  game.ui.showText('Ты вошёл в опасную зону!', 2);
});

// Игрок вышел из зоны
game.self.onUntouch(() => {
  game.ui.showText('Ты в безопасности', 1.5);
});`}</Code>
                    </>
                ),
            },
            {
                id: 'object-properties',
                title: 'B9. Свойства объекта: цвет, материал, физика, замок',
                body: (
                    <>
                        <p>
                            Когда ты выделяешь объект, в <b>Инспекторе</b> (правая
                            панель снизу) появляются его свойства:
                        </p>
                        <Shot src="b9-inspector.png"
                              caption="Инспектор свойств примитива: позиция, размер, цвет, материал" />
                        <table className="docTable">
                            <tbody>
                                <tr><td><b>Цвет</b></td><td>закрасить примитив в любой цвет</td></tr>
                                <tr><td><b>Материал</b></td><td>обычный, металл, стекло, неон — как объект блестит</td></tr>
                                <tr><td><b>Текстура</b></td><td>наложить свою картинку на поверхность</td></tr>
                                <tr><td><b>Столкновение</b></td><td>твёрдый объект или сквозь него можно пройти</td></tr>
                                <tr><td><b>Видимость</b></td><td>показать или спрятать объект</td></tr>
                                <tr><td><b>Закреплён</b></td><td>если выключить — объект падает под действием физики</td></tr>
                                <tr><td><b>Замок (Lock)</b></td><td>заблокировать, чтобы случайно не сдвинуть</td></tr>
                            </tbody>
                        </table>
                        <Note>
                            Свойство «Закреплён» — частая причина бага «объект
                            провалился сквозь пол». Для платформ, стен и декораций
                            всегда оставляй «Закреплён» включённым. Падать должны
                            только ящики и мячи, которым это нужно.
                        </Note>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ C — ИНТЕРФЕЙС ИГРЫ (GUI)
    // ════════════════════════════════════════════════════
    {
        id: 'gui',
        icon: 'window',
        title: 'Интерфейс игры',
        summary: 'GUI: кнопки, надписи, поля ввода, меню и счётчики поверх экрана.',
        sections: [
            {
                id: 'gui-what-is',
                title: 'C1. Что такое GUI и редактор интерфейса',
                body: (
                    <>
                        <p>
                            <b>GUI</b> (читается «гуи») — это интерфейс игры:
                            всё, что нарисовано поверх 3D-сцены. Кнопки, надписи,
                            счётчик очков, полоска здоровья, меню — это всё GUI.
                        </p>
                        <p>
                            GUI не находится внутри игрового мира — он «приклеен»
                            к экрану. Куда бы ни смотрел игрок, кнопка остаётся
                            на том же месте экрана.
                        </p>
                        <p>
                            В редакторе есть <b>визуальный редактор UI</b>: ты
                            перетаскиваешь элементы мышкой, ставишь их в нужное место,
                            меняешь цвет и текст — и сразу видишь результат. Открыть
                            его можно через инструмент <kbd className="kbd">Интерфейс</kbd>.
                        </p>
                        <Note>
                            Не путай <b>GUI</b> и <b>HUD</b>. GUI — это элементы,
                            которые ты сам нарисовал в редакторе интерфейса.
                            HUD — стандартные счётчики (<code>game.ui.score</code>,
                            <code> game.ui.timer</code>), которые рисует сама игра
                            по команде из скрипта.
                        </Note>
                    </>
                ),
            },
            {
                id: 'gui-elements',
                title: 'C2. Контейнер, надпись, кнопка, поле ввода, картинка',
                body: (
                    <>
                        <p>Из чего собирается интерфейс:</p>
                        <Shot src="c2-gui-palette.png"
                              caption="Палитра элементов интерфейса — перетащи на экран игры" />
                        <ul>
                            <li>
                                <b>Контейнер (Frame)</b> — прямоугольник-коробка.
                                Сам по себе это просто фон, но внутрь него кладут
                                другие элементы. Контейнер — основа любого меню.
                            </li>
                            <li>
                                <b>Надпись (Label)</b> — текст на экране. Счёт, имя
                                игрока, подсказки.
                            </li>
                            <li>
                                <b>Кнопка (Button)</b> — на неё можно нажать. По клику
                                в скрипте срабатывает действие.
                            </li>
                            <li>
                                <b>Поле ввода (TextBox)</b> — сюда игрок печатает текст
                                или число. Например, ввести код от двери.
                            </li>
                            <li>
                                <b>Картинка (Image)</b> — изображение: иконка, логотип,
                                фон меню.
                            </li>
                        </ul>
                        <p>
                            <b>Имя элемента.</b> Как и у объектов сцены, у GUI-элемента
                            есть имя. Скрипт находит элемент по имени командой
                            <code> game.gui.find('Кнопка старта')</code>. Давай
                            кнопкам и надписям понятные имена.
                        </p>
                    </>
                ),
            },
            {
                id: 'gui-script',
                title: 'C3. Как оживить кнопку скриптом',
                body: (
                    <>
                        <p>
                            Нарисованная кнопка сама по себе ничего не делает —
                            нужен скрипт. Самый простой способ — повесить скрипт
                            прямо на кнопку.
                        </p>
                        <ScriptKind kind="object" on="кнопку" />
                        <Code>{`// Скрипт висит на кнопке.
// game.self — это сама кнопка.
game.self.onClick(() => {
  game.ui.showText('Кнопка нажата!', 2);
  game.sound.play('click');
});`}</Code>
                        <p>
                            Можно и наоборот — управлять кнопкой из глобального
                            скрипта, если найти её по имени:
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Находим кнопку по имени и вешаем на неё клик
const btnId = game.gui.find('Кнопка старта');

game.gui.onClick(btnId, () => {
  game.ui.showText('Игра началась!', 2);
  // спрятать кнопку после нажатия
  game.gui.hide(btnId);
});`}</Code>
                        <p>
                            Что тут происходит: <code>game.gui.find</code> ищет
                            элемент по имени и возвращает его id («адрес»).
                            <code> game.gui.onClick</code> вешает на этот id действие.
                            <code> game.gui.hide</code> прячет кнопку, чтобы её нельзя
                            было нажать второй раз.
                        </p>
                    </>
                ),
            },
            {
                id: 'gui-textbox',
                title: 'C4. Поле ввода: дверь по коду',
                body: (
                    <>
                        <p>
                            <b>Поле ввода</b> позволяет игроку напечатать ответ.
                            Когда он нажмёт Enter, срабатывает событие
                            <code> onSubmit</code> — и скрипт получает введённый текст.
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Игрок вводит код. Правильный код — 1234.
const boxId = game.gui.find('Поле кода');

game.gui.onSubmit(boxId, (text) => {
  if (text === '1234') {
    game.ui.showText('Верно! Дверь открыта', 2);
    // двигаем дверь вверх, чтобы освободить проход
    const door = game.scene.findOne('Дверь');
    game.tween(door, { y: 8 }, { duration: 1 });
  } else {
    game.ui.showText('Неверный код', 1.5);
  }
});`}</Code>
                        <p>
                            Разберём построчно: <code>onSubmit</code> даёт переменную
                            <code> text</code> — это то, что напечатал игрок.
                            <code> if (text === '1234')</code> — проверяем, совпал ли
                            код. Если да — открываем дверь твином (плавно поднимаем).
                            Если нет — пишем «Неверный код».
                        </p>
                        <Note>
                            Две одинарные кавычки <code>'1234'</code> означают,
                            что это <b>текст</b>, а не число. Игрок печатает в поле
                            всегда текст, поэтому и сравнивать нужно с текстом.
                        </Note>
                    </>
                ),
            },
            {
                id: 'gui-styles',
                title: 'C5. Стили и загрузка картинок',
                body: (
                    <>
                        <p>
                            У каждого GUI-элемента в инспекторе настраивается внешний
                            вид: <b>цвет фона</b> и прозрачность, <b>граница</b>
                            (рамка, её цвет и толщина), <b>скругление углов</b>
                            (большое скругление делает кнопку «таблеткой»),
                            <b> тень</b> (мягкая тень под элементом),
                            <b> цвет и размер текста</b>.
                        </p>
                        <p>
                            В элемент <b>Картинка</b> можно загрузить своё изображение
                            с компьютера (PNG или JPG): логотип игры, иконку кнопки,
                            фон главного меню.
                        </p>
                        <Note>
                            Хороший интерфейс — это аккуратный интерфейс. Один стиль
                            для всех кнопок, один шрифт, выровненные отступы. Картинки
                            бери небольшие — огромные файлы делают игру тяжёлой.
                        </Note>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ D — СКРИПТЫ — ОСНОВЫ
    // ════════════════════════════════════════════════════
    {
        id: 'scripts-basics',
        icon: 'code',
        title: 'Скрипты — основы',
        summary: 'Самый важный раздел: что такое скрипт, переменные, события, таймеры.',
        sections: [
            {
                id: 'what-is-script',
                title: 'D1. Что такое скрипт и как его создать',
                body: (
                    <>
                        <p>
                            <b>Скрипт</b> — это набор команд, который оживляет игру.
                            Блоки и модели сами по себе просто стоят. Чтобы монетка
                            собиралась, дверь открывалась, а враг гнался за игроком —
                            нужен скрипт.
                        </p>
                        <p>
                            Скрипты пишут на языке <b>JavaScript</b> — одном из самых
                            популярных языков в мире. Не пугайся: начнём с простого,
                            а редактор подсказывает команды по ходу набора.
                        </p>
                        <p><b>Как создать первый скрипт:</b></p>
                        <Step n="1">
                            В иерархии (правая панель) найди категорию <b>Скрипты</b>
                            и нажми кнопку «+».
                        </Step>
                        <Shot src="d1-scripts-tree.png"
                              caption="Категория «Скрипты» в иерархии объектов" />
                        <Step n="2">
                            Откроется окно кода. Напиши в нём одну строку:
                        </Step>
                        <Code>{`game.log('Привет! Игра запустилась.');`}</Code>
                        <Shot src="d5-script-editor.png" wide
                              caption="Окно редактора кода скрипта" />
                        <Step n="3">
                            Нажми <kbd className="kbd">Играть</kbd>. Внизу справа
                            открой <b>Консоль</b> — там появится твоё сообщение.
                        </Step>
                        <p>
                            Это твой первый работающий скрипт. Команда
                            <code> game.log(...)</code> печатает сообщение в консоль.
                        </p>
                        <Note>
                            Каждая команда заканчивается точкой с запятой
                            <code> ;</code> — как точка в конце предложения. Текст
                            пишут в кавычках: <code>'привет'</code>. Забыл кавычки
                            или точку с запятой — будет ошибка.
                        </Note>
                    </>
                ),
            },
            {
                id: 'global-vs-object',
                title: 'D2. Глобальный скрипт и скрипт на объекте',
                body: (
                    <>
                        <p>
                            Это очень важно понять с самого начала. Скрипты бывают
                            <b> двух видов</b>, и в каждом уроке вики написано, какой
                            именно нужен.
                        </p>
                        <ScriptKind kind="global" />
                        <p>
                            Глобальный скрипт — это «мозг игры». Он не привязан
                            ни к чему. Запускается один раз при старте. В нём пишут
                            общие правила: подсчёт очков, таймер уровня, проверку
                            победы.
                        </p>
                        <ScriptKind kind="object" on="любой объект" />
                        <p>
                            Скрипт на объекте относится к конкретному кубу, модели
                            или кнопке. Внутри такого скрипта работает волшебное слово
                            <code> game.self</code> — это и есть тот объект, на котором
                            висит скрипт. Через него ловят клик по объекту или касание
                            игроком.
                        </p>
                        <p>
                            <b>Как привязать скрипт к объекту:</b> выдели объект
                            на сцене, потом создай скрипт — он автоматически привяжется
                            к выделенному объекту. Или укажи носителя в настройках
                            скрипта.
                        </p>
                        <Note>
                            Простое правило: если в коде урока есть
                            <code> game.self</code> — это скрипт <b>на объекте</b>.
                            Если <code>game.self</code> нет — скрипт <b>глобальный</b>.
                            Плашка в начале каждого урока всегда подскажет.
                        </Note>
                    </>
                ),
            },
            {
                id: 'variables',
                title: 'D3. Переменные — память скрипта',
                body: (
                    <>
                        <p>
                            <b>Переменная</b> — это «коробочка с именем», в которой
                            скрипт хранит значение. Например, количество очков,
                            имя игрока, выбранный уровень.
                        </p>
                        <Code>{`// Создаём переменную и кладём в неё число
let score = 0;

// Меняем значение
score = score + 10;   // теперь в score лежит 10
score = score + 5;    // теперь 15

game.log('Очков:', score);   // напечатает: Очков: 15`}</Code>
                        <p>
                            <code>let</code> — это слово «создать переменную». Пишут
                            его только <b>один раз</b>, когда коробочку заводят. Дальше
                            меняют значение уже без <code>let</code>.
                        </p>
                        <p>В переменную можно класть не только числа:</p>
                        <Code>{`let name = 'Герой';        // текст — в кавычках
let isWin = false;         // да/нет — true или false
let coinCount = 0;         // число — без кавычек`}</Code>
                        <Note>
                            Если значение <b>никогда</b> не меняется — вместо
                            <code> let</code> можно писать <code>const</code>
                            («постоянная»). Например, найденную один раз дверь:
                            <code> const door = game.scene.findOne('Дверь');</code>
                        </Note>
                    </>
                ),
            },
            {
                id: 'game-object',
                title: 'D4. Объект game — главный инструмент',
                body: (
                    <>
                        <p>
                            В каждом скрипте есть одно главное волшебное слово —
                            <code> game</code>. Через него ты управляешь всей игрой.
                            У <code>game</code> много «отделов»:
                        </p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>game.player</code></td><td>управление игроком</td></tr>
                                <tr><td><code>game.scene</code></td><td>объекты сцены</td></tr>
                                <tr><td><code>game.ui</code></td><td>счётчики и текст на экране</td></tr>
                                <tr><td><code>game.gui</code></td><td>кнопки и меню</td></tr>
                                <tr><td><code>game.sound</code></td><td>звуки</td></tr>
                                <tr><td><code>game.physics</code></td><td>лучи, импульсы, взрывы</td></tr>
                                <tr><td><code>game.self</code></td><td>объект-носитель скрипта</td></tr>
                            </tbody>
                        </table>
                        <p>
                            Запись через точку читается слева направо.
                            <code> game.player.teleport(0, 5, 0)</code> читается так:
                            «у <b>игры</b>, у <b>игрока</b>, выполни <b>телепорт</b>
                            в точку 0, 5, 0».
                        </p>
                        <p>
                            Полный список всех команд каждого отдела — в Справочнике
                            (раздел H). Не нужно его заучивать: при наборе кода
                            редактор сам показывает подсказки.
                        </p>
                    </>
                ),
            },
            {
                id: 'log-console',
                title: 'D5. game.log, консоль, отладка',
                body: (
                    <>
                        <p>
                            <b>Консоль</b> — окошко в правом нижнем углу редактора.
                            Туда выводятся все сообщения и ошибки скриптов.
                        </p>
                        <p>
                            Команда <code>game.log(...)</code> печатает в консоль
                            что угодно. Это главный инструмент <b>отладки</b> —
                            проверки, что код работает правильно:
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`let score = 0;
score = score + 10;
game.log('Очки сейчас:', score);  // Очки сейчас: 10

let pos = game.player.position;
game.log('Игрок стоит в точке:', pos);`}</Code>
                        <p>
                            Если игра ведёт себя странно — расставь
                            <code> game.log</code> по коду и посмотри, какие значения
                            печатаются. Так ты увидишь, где именно что-то пошло не так.
                        </p>
                        <Note>
                            Если в скрипте опечатка — текст ошибки появится
                            в Консоли <b>красным</b>, и там же будет написан номер
                            строки с ошибкой. Всегда заглядывай в Консоль первым делом.
                        </Note>
                    </>
                ),
            },
            {
                id: 'events',
                title: 'D6. События: onTick, onKey, onClick, onTouch',
                body: (
                    <>
                        <p>
                            <b>Событие</b> — это «что-то случилось». Скрипт может
                            ждать событие и реагировать на него. Самые важные:
                        </p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>game.onTick(fn)</code></td><td>каждый кадр (60 раз в секунду)</td></tr>
                                <tr><td><code>game.onKey('space', fn)</code></td><td>игрок нажал клавишу</td></tr>
                                <tr><td><code>game.self.onClick(fn)</code></td><td>игрок кликнул по объекту</td></tr>
                                <tr><td><code>game.self.onTouch(fn)</code></td><td>игрок коснулся объекта</td></tr>
                            </tbody>
                        </table>
                        <p>Пример — куб, который исчезает по клику:</p>
                        <ScriptKind kind="object" on="куб" />
                        <Code>{`game.self.onClick(() => {
  game.self.delete();          // удалить сам себя
  game.log('Куб удалён!');
});`}</Code>
                        <p>
                            <b>Что такое <code>{`() => { ... }`}</code>?</b> Это
                            «функция» — набор команд, упакованных вместе. Команды
                            внутри фигурных скобок выполнятся <b>не сразу</b>, а только
                            когда случится событие. То есть «когда кликнули — тогда
                            удалить и напечатать».
                        </p>
                        <Note>
                            <code>onTick</code> выполняется ОЧЕНЬ часто — 60 раз
                            в секунду. Не делай внутри него тяжёлых вещей. Подробнее
                            об этой ошибке — раздел J4.
                        </Note>
                    </>
                ),
            },
            {
                id: 'conditions',
                title: 'D7. Условия: if / else',
                body: (
                    <>
                        <p>
                            <b>Условие</b> — это развилка: «<b>если</b> что-то верно —
                            сделай одно, <b>иначе</b> — другое». В JavaScript это
                            слова <code>if</code> («если») и <code>else</code>
                            («иначе»).
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`let coins = 7;

if (coins >= 10) {
  game.ui.showText('Хватает на покупку!', 2);
} else {
  game.ui.showText('Нужно больше монет', 2);
}`}</Code>
                        <p>
                            Тут проверяется: <code>coins {'>'}= 10</code> — «монет
                            10 или больше?». Сейчас монет 7, значит условие неверно,
                            и сработает ветка <code>else</code>.
                        </p>
                        <p><b>Знаки сравнения:</b></p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>a === b</code></td><td>a равно b</td></tr>
                                <tr><td><code>a !== b</code></td><td>a не равно b</td></tr>
                                <tr><td><code>a {'>'} b</code></td><td>a больше b</td></tr>
                                <tr><td><code>a {'<'} b</code></td><td>a меньше b</td></tr>
                                <tr><td><code>a {'>'}= b</code></td><td>a больше или равно b</td></tr>
                                <tr><td><code>a {'<'}= b</code></td><td>a меньше или равно b</td></tr>
                            </tbody>
                        </table>
                        <Note>
                            Для проверки «равно» пишут <b>три</b> знака равенства
                            <code> ===</code>, а не один. Один знак <code>=</code> —
                            это «положить значение в переменную», совсем другое
                            действие.
                        </Note>
                    </>
                ),
            },
            {
                id: 'timers',
                title: 'D8. Таймеры: after, every, cancel',
                body: (
                    <>
                        <p>
                            Таймеры запускают команды <b>не сразу, а потом</b>:
                        </p>
                        <ul>
                            <li>
                                <code>game.after(сек, fn)</code> — выполнить
                                <b> один раз</b> через несколько секунд;
                            </li>
                            <li>
                                <code>game.every(сек, fn)</code> — выполнять
                                <b> снова и снова</b> каждые несколько секунд;
                            </li>
                            <li>
                                <code>game.cancel(id)</code> — остановить таймер.
                            </li>
                        </ul>
                        <ScriptKind kind="global" />
                        <Code>{`// Через 3 секунды показать текст
game.after(3, () => {
  game.ui.showText('Игра началась!', 2);
});

// Каждую секунду прибавлять очко.
// every возвращает номер таймера — запомним его.
const ticker = game.every(1, () => {
  game.ui.score = (game.ui.score || 0) + 1;
});

// Через 10 секунд остановить начисление очков
game.after(10, () => {
  game.cancel(ticker);
  game.ui.showText('Время вышло!', 2);
});`}</Code>
                        <p>
                            Запись <code>(game.ui.score || 0)</code> читается так:
                            «возьми счёт, а если его ещё нет — возьми 0». Это защита
                            от ошибки в самом начале, когда счётчик ещё пустой.
                        </p>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ E — СКРИПТЫ — ДВИЖЕНИЕ И АНИМАЦИЯ
    // ════════════════════════════════════════════════════
    {
        id: 'scripts-motion',
        icon: 'run',
        title: 'Движение и анимация',
        summary: 'Управление игроком, плавные твины, спавн и перемещение объектов.',
        sections: [
            {
                id: 'player-control',
                title: 'E1. Управление игроком: скорость, прыжок, гравитация',
                body: (
                    <>
                        <p>
                            Скриптом можно менять, как двигается игрок. Эти команды
                            принимают <b>множитель</b>: 1 — обычно, 2 — в два раза
                            сильнее, 0.5 — в два раза слабее.
                        </p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>setSpeed(mul)</code></td><td>скорость бега</td></tr>
                                <tr><td><code>setJumpPower(mul)</code></td><td>сила прыжка</td></tr>
                                <tr><td><code>setGravityMul(mul)</code></td><td>сила притяжения</td></tr>
                                <tr><td><code>setDoubleJump(true)</code></td><td>разрешить двойной прыжок</td></tr>
                                <tr><td><code>teleport(x,y,z)</code></td><td>мгновенно переставить</td></tr>
                            </tbody>
                        </table>
                        <p>Пример — «зелье скорости» при касании сферы:</p>
                        <ScriptKind kind="object" on="сфера-зелье" />
                        <Code>{`game.self.onTouch(() => {
  // ускоряем игрока в 2 раза
  game.player.setSpeed(2);
  game.ui.showText('Скорость x2 на 5 секунд!', 2);
  game.sound.play('pickup');

  // зелье исчезает
  game.self.delete();

  // через 5 секунд скорость снова обычная
  game.after(5, () => {
    game.player.setSpeed(1);
  });
});`}</Code>
                        <Note>
                            Не забывай возвращать скорость обратно командой
                            <code> setSpeed(1)</code>. Иначе игрок останется быстрым
                            навсегда — а это может сломать твой уровень.
                        </Note>
                    </>
                ),
            },
            {
                id: 'player-animations',
                title: 'E2. Анимации-эмоции персонажа',
                body: (
                    <>
                        <p>
                            Персонаж умеет показывать эмоции. Команда
                            <code> game.player.playAnimation(имя)</code> проигрывает
                            анимацию: <code>'wave'</code> (помахать),
                            <code> 'dance'</code> (танец), <code>'cheer'</code>
                            (радость), <code>'sit'</code> (сесть).
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// При победе персонаж радуется
game.player.playAnimation('cheer');

// Через 3 секунды перестать
game.after(3, () => {
  game.player.stopAnimation();
});`}</Code>
                    </>
                ),
            },
            {
                id: 'tweens',
                title: 'E3. Твины — плавные движения',
                body: (
                    <>
                        <p>
                            <b>Твин</b> — это плавное изменение чего-либо за время.
                            Если просто переставить объект командой <code>move</code> —
                            он телепортируется рывком. А твин <b>плавно</b> доедет
                            из точки в точку.
                        </p>
                        <p>Команда: <code>game.tween(объект, что менять, настройки)</code></p>
                        <ScriptKind kind="global" />
                        <Code>{`// Находим платформу-лифт по имени
const lift = game.scene.findOne('Лифт');

// Платформа за 2 секунды плавно поднимается на высоту 10
game.tween(lift, { y: 10 }, {
  duration: 2,        // длительность в секундах
  easing: 'ease'      // характер движения
});`}</Code>
                        <p>
                            Твином можно менять позицию (<code>x, y, z</code>),
                            поворот, размер, цвет, прозрачность.
                        </p>
                        <p><b>Полезные настройки твина:</b></p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>duration</code></td><td>сколько секунд длится</td></tr>
                                <tr><td><code>easing</code></td><td>'linear' (ровно), 'ease' (плавно), 'bounce' (с отскоком)</td></tr>
                                <tr><td><code>repeat</code></td><td>сколько раз повторить</td></tr>
                                <tr><td><code>yoyo: true</code></td><td>двигаться туда-обратно</td></tr>
                                <tr><td><code>onDone</code></td><td>что сделать, когда твин закончится</td></tr>
                            </tbody>
                        </table>
                        <Code>{`// Платформа вечно ездит вверх-вниз
const plat = game.scene.findOne('Качалка');
game.tween(plat, { y: 8 }, {
  duration: 2,
  yoyo: true,      // обратно вниз
  repeat: 999      // повторять почти бесконечно
});`}</Code>
                    </>
                ),
            },
            {
                id: 'spawn-delete',
                title: 'E4. Спавн и удаление объектов',
                body: (
                    <>
                        <p>
                            <b>Спавн</b> — создание нового объекта прямо во время игры.
                            Команда <code>game.scene.spawn(тип, настройки)</code>:
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Создаём золотую монетку-сферу
const coin = game.scene.spawn('primitive:sphere', {
  x: 5, y: 1, z: 0,    // где появится
  color: '#ffd700'     // золотой цвет
});

game.log('Создали монетку, её адрес:', coin);`}</Code>
                        <p>
                            Тип бывает <code>'block:трава'</code>,
                            <code> 'primitive:cube'</code>, <code>'model:tree'</code>.
                            Команда <b>возвращает ref</b> — это «адрес» объекта,
                            по которому к нему можно обращаться (двигать, удалять).
                        </p>
                        <p><b>Удаление объекта:</b></p>
                        <Code>{`// удалить сразу
game.scene.delete(coin);

// удалить через 3 секунды
game.scene.deleteAfter(coin, 3);`}</Code>
                        <Note>
                            Запоминай <code>ref</code> в переменную (<code>let coin
                            = ...</code>). Без адреса ты потом не сможешь объект
                            ни подвинуть, ни удалить.
                        </Note>
                    </>
                ),
            },
            {
                id: 'move-objects',
                title: 'E5. Перемещение объектов',
                body: (
                    <>
                        <p>Передвинуть объект скриптом можно несколькими способами:</p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>game.scene.move(ref,x,y,z)</code></td><td>мгновенно переставить</td></tr>
                                <tr><td><code>game.scene.rotate(ref,угол)</code></td><td>повернуть</td></tr>
                                <tr><td><code>game.self.move(x,y,z)</code></td><td>скрипт двигает сам себя</td></tr>
                                <tr><td><code>game.tween(...)</code></td><td>плавное перемещение (E3)</td></tr>
                            </tbody>
                        </table>
                        <p>Пример — дверь уезжает вверх и освобождает проход:</p>
                        <ScriptKind kind="global" />
                        <Code>{`const door = game.scene.findOne('Дверь');

// плавно поднимаем дверь на 6 единиц вверх
game.tween(door, { y: 6 }, { duration: 1 });`}</Code>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ F — СКРИПТЫ — ИГРОВАЯ ЛОГИКА
    // ════════════════════════════════════════════════════
    {
        id: 'scripts-logic',
        icon: 'target',
        title: 'Игровая логика',
        summary: 'HP и урон, физика, теги, взаимодействие по E, связи между объектами.',
        sections: [
            {
                id: 'player-hp',
                title: 'F1. HP игрока: урон, лечение, смерть, чекпоинт',
                body: (
                    <>
                        <p>Команды для здоровья игрока:</p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>game.player.hp</code></td><td>текущее здоровье (можно читать)</td></tr>
                                <tr><td><code>game.player.damage(n)</code></td><td>нанести урон</td></tr>
                                <tr><td><code>game.player.heal(n)</code></td><td>вылечить</td></tr>
                                <tr><td><code>game.player.kill()</code></td><td>мгновенно убить</td></tr>
                                <tr><td><code>game.player.respawn()</code></td><td>воскресить на спавне</td></tr>
                                <tr><td><code>game.player.setSpawn(точка)</code></td><td>новая точка возрождения</td></tr>
                            </tbody>
                        </table>
                        <p><b>Пример 1 — шипы наносят урон:</b></p>
                        <ScriptKind kind="object" on="шипы (конус)" />
                        <Code>{`game.self.onTouch(() => {
  game.player.damage(20);     // отнять 20 здоровья
  game.sound.play('hit');
});`}</Code>
                        <p><b>Пример 2 — аптечка лечит:</b></p>
                        <ScriptKind kind="object" on="аптечку" />
                        <Code>{`game.self.onTouch(() => {
  game.player.heal(50);       // добавить 50 здоровья
  game.ui.showText('+50 HP', 1.5);
  game.self.delete();         // аптечка исчезает
});`}</Code>
                    </>
                ),
            },
            {
                id: 'physics',
                title: 'F2. Физика: raycast, импульсы, взрывы',
                body: (
                    <>
                        <p>
                            Отдел <code>game.physics</code> отвечает за «настоящую»
                            физику:
                        </p>
                        <ul>
                            <li>
                                <code>raycast(откуда, куда, опции)</code> — пустить
                                невидимый луч и узнать, во что он попал. Так делают
                                стрельбу;
                            </li>
                            <li>
                                <code>applyImpulse(ref, сила)</code> — толкнуть объект
                                (он должен быть не закреплён);
                            </li>
                            <li>
                                <code>explode(точка, радиус, опции)</code> — взрыв.
                            </li>
                        </ul>
                        <p><b>Пример — стрельба лучом из камеры игрока:</b></p>
                        <ScriptKind kind="global" />
                        <Code>{`// При клике мышкой пускаем луч туда, куда смотрит игрок
game.onClick(() => {
  const p = game.player.position;

  const hit = game.physics.raycast(
    { x: p.x, y: p.y + 1.5, z: p.z },  // откуда (от головы)
    game.player.forward,                // куда (взгляд)
    { maxDistance: 50 }                 // как далеко
  );

  if (hit.hit) {
    game.log('Попал в объект:', hit.ref);
    game.sound.play('hit');
  }
});`}</Code>
                        <p>
                            <code>hit.hit</code> — попал ли луч во что-нибудь
                            (да/нет). <code>hit.ref</code> — адрес объекта, в который
                            попали.
                        </p>
                    </>
                ),
            },
            {
                id: 'attributes',
                title: 'F3. Атрибуты объектов (setData / getData)',
                body: (
                    <>
                        <p>
                            <b>Атрибут</b> — это значение, которое ты «приклеиваешь»
                            к объекту. Например, сколько здоровья у конкретного врага
                            или сколько монет стоит товар.
                        </p>
                        <ScriptKind kind="object" on="товар в магазине" />
                        <Code>{`// При старте игры запоминаем цену прямо на товаре
game.scene.setData(game.self.ref, 'price', 50);

// Когда игрок кликает по товару — читаем цену
game.self.onClick(() => {
  const price = game.scene.getData(game.self.ref, 'price');
  game.ui.showText('Этот товар стоит ' + price + ' монет', 2);
});`}</Code>
                        <p>
                            Чем атрибут лучше обычной переменной? Переменная одна
                            на весь скрипт. А атрибут — свой у каждого объекта.
                            Один и тот же скрипт можно повесить на 10 разных товаров,
                            и у каждого будет своя цена.
                        </p>
                    </>
                ),
            },
            {
                id: 'tags',
                title: 'F4. Теги объектов',
                body: (
                    <>
                        <p>
                            <b>Тег</b> — это «ярлык», который можно повесить сразу
                            на много объектов. Потом одной командой можно найти их все.
                        </p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>tag(ref, 'звезда')</code></td><td>повесить тег</td></tr>
                                <tr><td><code>untag(ref, 'звезда')</code></td><td>снять тег</td></tr>
                                <tr><td><code>hasTag(ref, 'звезда')</code></td><td>есть ли тег</td></tr>
                                <tr><td><code>getTagged('звезда')</code></td><td>все объекты с тегом</td></tr>
                            </tbody>
                        </table>
                        <p><b>Пример — игра «собери все звёзды»:</b></p>
                        <ScriptKind kind="object" on="каждую звезду" />
                        <Code>{`// Этот скрипт висит на звезде.
// При старте помечаем звезду тегом.
game.scene.tag(game.self.ref, 'звезда');

// Когда игрок коснулся — звезда собрана
game.self.onTouch(() => {
  game.self.delete();
  game.sound.play('coin');

  // сколько звёзд ещё осталось на сцене?
  const left = game.scene.getTagged('звезда').length;
  if (left === 0) {
    game.ui.showText('Все звёзды собраны! Победа!', 3);
  } else {
    game.ui.showText('Осталось звёзд: ' + left, 1.5);
  }
});`}</Code>
                        <Note>
                            Снятие тега убирает только ярлык. Цвет, размер и другие
                            свойства объекта при этом не меняются.
                        </Note>
                    </>
                ),
            },
            {
                id: 'proximity',
                title: 'F5. ProximityPrompt — взаимодействие по клавише E',
                body: (
                    <>
                        <p>
                            Часто игра просит «подойди и нажми E»: открыть сундук,
                            поговорить с торговцем, дёрнуть рычаг. Это делается
                            командой <code>game.self.onInteract</code>:
                        </p>
                        <ScriptKind kind="object" on="сундук" />
                        <Code>{`game.self.onInteract(() => {
  game.ui.showText('Сундук открыт!', 2);
  game.scene.spawnParticles('sparks',
    game.self.position, { duration: 1 });
  game.sound.play('pickup');
}, {
  text: 'Открыть сундук',   // подсказка над объектом
  distance: 4               // на сколько метров подойти
});`}</Code>
                        <p>
                            Когда игрок подойдёт ближе чем на <code>distance</code>
                            метров, над объектом появится подсказка с текстом.
                            Нажатие <kbd className="kbd">E</kbd> запустит функцию.
                        </p>
                    </>
                ),
            },
            {
                id: 'billboard',
                title: 'F6. Billboard-метки над объектами',
                body: (
                    <>
                        <p>
                            <b>Billboard</b> — это текст-табличка, которая висит
                            над объектом в 3D-мире и всегда повёрнута к игроку.
                            Так показывают имена врагов, их HP, названия мест.
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Допустим, npc — это адрес созданного NPC.
// Вешаем над ним табличку с именем.
game.scene.setLabel(npc.ref, 'Торговец Боб', {
  color: '#ffffff',
  height: 2.5     // на 2.5 метра над объектом
});

// Позже можно убрать табличку
game.scene.clearLabel(npc.ref);`}</Code>
                    </>
                ),
            },
            {
                id: 'pass-through',
                title: 'F7. Проходимость объектов (passThrough)',
                body: (
                    <>
                        <p>
                            Иногда стена должна стать проходимой — призрачная стена,
                            секретный проход, исчезающий мост. Команда
                            <code> game.physics.passThrough(ref, true)</code> делает
                            объект «бесплотным»: видно его, но игрок проходит насквозь.
                        </p>
                        <ScriptKind kind="object" on="секретную стену" />
                        <Code>{`// Когда игрок кликнет по стене — она пропустит сквозь себя
game.self.onClick(() => {
  game.physics.passThrough(game.self.ref, true);
  game.scene.setOpacity(game.self.ref, 0.3);  // полупрозрачная
  game.ui.showText('Секретный проход открыт!', 2);
});`}</Code>
                        <Note>
                            Если сделать стену снова твёрдой, пока игрок стоит внутри
                            неё — игра аккуратно вытолкнет его наружу, он не застрянет.
                        </Note>
                    </>
                ),
            },
            {
                id: 'constraints',
                title: 'F8. Связи: склейка, петля, пружина',
                body: (
                    <>
                        <p>
                            <b>Связи (constraints)</b> соединяют объекты, чтобы они
                            двигались вместе или по правилам физики. Отдел —
                            <code> game.constraints</code>:
                        </p>
                        <ul>
                            <li>
                                <b>Склейка (weld)</b> — намертво приклеивает один
                                объект к другому;
                            </li>
                            <li>
                                <b>Петля (hinge)</b> — объект вращается вокруг оси,
                                как дверь на петлях или качели;
                            </li>
                            <li>
                                <b>Пружина (spring)</b> — объект упруго колеблется,
                                как батут.
                            </li>
                        </ul>
                        <p><b>Пример — качели на петле:</b></p>
                        <ScriptKind kind="global" />
                        <Code>{`const swing = game.scene.findOne('Качели');

// делаем качели на петле
const h = game.constraints.hinge(swing, {
  pivotX: 0, pivotZ: 0,   // ось вращения
  angle: 30               // наклон на 30 градусов
});

// раскачиваем в другую сторону каждую секунду
let dir = -30;
game.every(1, () => {
  h.setAngle(dir);
  dir = -dir;   // меняем знак: 30 → -30 → 30 ...
});`}</Code>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ G — СКРИПТЫ — БОЛЬШИЕ СИСТЕМЫ
    // ════════════════════════════════════════════════════
    {
        id: 'scripts-systems',
        icon: 'gear',
        title: 'Большие системы',
        summary: 'NPC, инвентарь и оружие, звук, камера и катсцены, мультиплеер.',
        sections: [
            {
                id: 'npc',
                title: 'G1. NPC: создание, движение, диалоги',
                body: (
                    <>
                        <p>
                            <b>NPC</b> (неигровой персонаж) — это житель твоей игры:
                            торговец, враг, проводник. Создаётся командой
                            <code> game.scene.spawnNpc(модель, опции)</code>.
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Создаём NPC по имени Боб
const bob = game.scene.spawnNpc('character-a', {
  x: 5, y: 0, z: 0,
  name: 'Боб',
  hp: 100,
  speed: 3
});

// Боб говорит реплику над головой (3 секунды)
bob.say('Привет, путник!', 3);

// Боб идёт в точку (x = 10, z = 0)
bob.moveTo(10, 0);`}</Code>
                        <p><b>Что умеет NPC:</b></p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>moveTo(x, z)</code></td><td>идти в точку</td></tr>
                                <tr><td><code>follow('player')</code></td><td>гнаться за игроком</td></tr>
                                <tr><td><code>stop()</code></td><td>остановиться</td></tr>
                                <tr><td><code>say(текст, сек)</code></td><td>реплика над головой</td></tr>
                                <tr><td><code>damage(n)</code></td><td>нанести урон NPC</td></tr>
                                <tr><td><code>remove()</code></td><td>убрать со сцены</td></tr>
                                <tr><td><code>onDeath(fn)</code></td><td>что сделать при гибели</td></tr>
                            </tbody>
                        </table>
                        <p><b>Пример — враг гонится за игроком:</b></p>
                        <Code>{`const enemy = game.scene.spawnNpc('character-b', {
  x: 0, y: 0, z: 20, name: 'Враг', hp: 50, speed: 2
});

enemy.follow('player');   // началась погоня

enemy.onDeath(() => {
  game.ui.showText('Враг побеждён!', 2);
  game.scene.spawnParticles('explosion',
    enemy.position, { duration: 1 });
});`}</Code>
                    </>
                ),
            },
            {
                id: 'inventory-tools',
                title: 'G2. Инвентарь и инструменты',
                body: (
                    <>
                        <p>
                            <b>Инвентарь</b> — это сумка предметов внизу экрана.
                            <b> Инструмент</b> — предмет, который игрок берёт в руку:
                            меч, фонарик, лопата.
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Выдать игроку меч прямо в руку
game.player.giveTool('sword', {
  name: 'Стальной меч',
  equip: true   // сразу взять в руку
});

// Ловим, когда игрок применил инструмент (ЛКМ)
game.player.onToolUse((e) => {
  game.log('Игрок применил:', e.tool);
});`}</Code>
                        <p>
                            Команды отдела <code>game.inventory</code>:
                            <code> add(item)</code> — добавить предмет,
                            <code> remove(имя)</code> — убрать,
                            <code> has(имя)</code> — есть ли предмет,
                            <code> list()</code> — список всех предметов.
                        </p>
                        <p><b>Пример — игра «ключ и сундук»:</b></p>
                        <ScriptKind kind="object" on="сундук" />
                        <Code>{`game.self.onInteract(() => {
  // проверяем, есть ли у игрока ключ
  if (game.inventory.has('Ключ')) {
    game.ui.showText('Сундук открыт!', 2);
    game.inventory.remove('Ключ');   // ключ потрачен
  } else {
    game.ui.showText('Нужен ключ', 1.5);
  }
}, { text: 'Открыть', distance: 4 });`}</Code>
                    </>
                ),
            },
            {
                id: 'sound',
                title: 'G3. Звук: свои звуки и 3D-позиционный звук',
                body: (
                    <>
                        <p>
                            Звук оживляет игру. Команда
                            <code> game.sound.play(id, опции)</code>.
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Готовые звуки-пресеты
game.sound.play('coin');   // звон монетки
game.sound.play('win');    // победа
game.sound.play('jump');   // прыжок
game.sound.play('hit');    // удар

// Свой загруженный звук, потише
game.sound.play('sound_1', { volume: 0.7 });`}</Code>
                        <p>
                            Пресеты: <code>jump</code>, <code>pickup</code>,
                            <code> win</code>, <code>lose</code>, <code>click</code>,
                            <code> hit</code>, <code>coin</code>.
                        </p>
                        <p>
                            <b>3D-звук</b> — если указать опцию <code>at</code>,
                            звук пойдёт из точки в мире: чем дальше игрок, тем тише.
                        </p>
                        <Code>{`// Звук костра — слышен только когда подходишь близко
game.sound.play('sound_2', {
  at: { x: 0, y: 1, z: 0 },
  loop: true     // звук повторяется по кругу
});`}</Code>
                        <Note>
                            Звук в играх обязателен — игра без звука кажется
                            «мёртвой». Но не запускай длинную музыку в самом начале:
                            это скучно и тормозит старт. Звуки вешай на события:
                            прыжок, попадание, победа.
                        </Note>
                    </>
                ),
            },
            {
                id: 'camera',
                title: 'G4. Камера: FOV, привязка, катсцены',
                body: (
                    <>
                        <p>Отдел <code>game.camera</code> управляет видом игрока:</p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>setFov(градусы)</code></td><td>угол обзора — больше «шире» видно</td></tr>
                                <tr><td><code>shake(сила, сек)</code></td><td>тряска камеры (взрыв, удар)</td></tr>
                                <tr><td><code>focusOn(ref)</code></td><td>навести камеру на объект</td></tr>
                                <tr><td><code>cutscene(точки, опции)</code></td><td>пролёт камеры по точкам</td></tr>
                                <tr><td><code>reset()</code></td><td>вернуть камеру игроку</td></tr>
                            </tbody>
                        </table>
                        <p><b>Пример — облёт уровня при старте игры:</b></p>
                        <ScriptKind kind="global" />
                        <Code>{`// камера плавно пролетает через три точки
game.camera.cutscene([
  { x: 0, y: 20, z: -30 },
  { x: 0, y: 15, z: 0 },
  { x: 0, y: 10, z: 30 }
], { segDuration: 2 });   // 2 секунды на отрезок

// когда облёт закончится — отдать камеру игроку
game.onCutsceneDone(() => {
  game.ui.showText('Поехали!', 2);
});`}</Code>
                    </>
                ),
            },
            {
                id: 'beam-trail',
                title: 'G5. Лучи и следы (Beam и Trail)',
                body: (
                    <>
                        <p>
                            Отдел <code>game.fx</code> создаёт красивые эффекты-линии:
                            <b> Beam</b> — светящаяся линия между двумя точками
                            (лазер, мост света), <b>Trail</b> — шлейф за движущимся
                            объектом (след за ракетой).
                        </p>
                        <ScriptKind kind="global" />
                        <Code>{`// Лазер между двумя башнями
const t1 = game.scene.findOne('Башня1');
const t2 = game.scene.findOne('Башня2');

const laser = game.fx.beam({
  from: t1,
  to: t2,
  color: '#ff3344',
  width: 0.3
});`}</Code>
                    </>
                ),
            },
            {
                id: 'multiplayer',
                title: 'G6. Мультиплеер: игроки, комната, команды',
                body: (
                    <>
                        <p>
                            В Рублоксе можно сделать игру на несколько игроков
                            в одной комнате. Главные отделы:
                        </p>
                        <ul>
                            <li>
                                <code>game.players</code> — список игроков:
                                <code> all()</code>, <code>count()</code>,
                                <code> me()</code> (это я);
                            </li>
                            <li>
                                <code>game.room</code> — общее состояние комнаты,
                                которое видят все игроки;
                            </li>
                            <li>
                                <code>game.teams</code> — команды.
                            </li>
                        </ul>
                        <ScriptKind kind="global" />
                        <Code>{`// Общий счёт команды — виден всем игрокам в комнате
game.room.set('totalScore', 0);

// когда счёт меняется — обновляем надпись у всех
game.room.onChange('totalScore', (val) => {
  game.ui.set('score', 'Счёт команды: ' + val);
});

// сколько игроков сейчас в игре
game.log('Игроков в комнате:', game.players.count());

// когда новый игрок зашёл
game.onPlayerJoin((p) => {
  game.ui.showText(p.name + ' присоединился!', 2);
});`}</Code>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ H — СПРАВОЧНИК game.*
    // ════════════════════════════════════════════════════
    {
        id: 'reference',
        icon: 'book',
        title: 'Справочник game.*',
        summary: 'Шпаргалка: все команды game.* списком по отделам.',
        sections: [
            {
                id: 'cheatsheet',
                title: 'H1. Шпаргалка — все команды списком',
                body: (
                    <>
                        <p>
                            Здесь собраны все команды <code>game.*</code> по отделам.
                            Это шпаргалка — не нужно её запоминать, держи под рукой.
                        </p>

                        <h4 className="docRefHead"><DocIcon name="run" size={17} /> game.player — игрок</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>position</code></td><td>позиция игрока {`{x,y,z}`}</td></tr>
                                <tr><td><code>hp</code> / <code>maxHp</code></td><td>здоровье и максимум</td></tr>
                                <tr><td><code>alive</code></td><td>жив ли игрок (да/нет)</td></tr>
                                <tr><td><code>forward</code></td><td>куда смотрит {`{x,y,z}`}</td></tr>
                                <tr><td><code>teleport(x,y,z)</code></td><td>телепорт</td></tr>
                                <tr><td><code>damage(n)</code> / <code>heal(n)</code></td><td>урон / лечение</td></tr>
                                <tr><td><code>kill()</code> / <code>respawn()</code></td><td>убить / воскресить</td></tr>
                                <tr><td><code>setSpawn(точка)</code></td><td>новая точка возрождения</td></tr>
                                <tr><td><code>setSpeed(mul)</code></td><td>скорость бега</td></tr>
                                <tr><td><code>setJumpPower(mul)</code></td><td>сила прыжка</td></tr>
                                <tr><td><code>setGravityMul(mul)</code></td><td>сила гравитации</td></tr>
                                <tr><td><code>setDoubleJump(on)</code></td><td>двойной прыжок</td></tr>
                                <tr><td><code>playAnimation(имя)</code></td><td>эмоция персонажа</td></tr>
                                <tr><td><code>giveTool(тип,опции)</code></td><td>дать инструмент</td></tr>
                                <tr><td><code>isKeyDown(клавиша)</code></td><td>зажата ли клавиша сейчас</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="cube" size={17} /> game.scene — объекты сцены</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>spawn(тип,опции)</code></td><td>создать объект → ref</td></tr>
                                <tr><td><code>delete(ref)</code></td><td>удалить</td></tr>
                                <tr><td><code>deleteAfter(ref,сек)</code></td><td>удалить через N секунд</td></tr>
                                <tr><td><code>move(ref,x,y,z)</code></td><td>переместить</td></tr>
                                <tr><td><code>rotate(ref,угол)</code></td><td>повернуть</td></tr>
                                <tr><td><code>setColor(ref,цвет)</code></td><td>сменить цвет</td></tr>
                                <tr><td><code>setCollide(ref,да)</code></td><td>твёрдость</td></tr>
                                <tr><td><code>setVisible(ref,да)</code></td><td>видимость</td></tr>
                                <tr><td><code>setOpacity(ref,0..1)</code></td><td>прозрачность</td></tr>
                                <tr><td><code>find(имя)</code> / <code>findOne(имя)</code></td><td>поиск по имени</td></tr>
                                <tr><td><code>all(тип)</code></td><td>все объекты типа</td></tr>
                                <tr><td><code>getPosition(ref)</code></td><td>позиция объекта</td></tr>
                                <tr><td><code>setData/getData</code></td><td>атрибуты объекта</td></tr>
                                <tr><td><code>tag/untag/hasTag</code></td><td>теги</td></tr>
                                <tr><td><code>getTagged(тег)</code></td><td>все объекты с тегом</td></tr>
                                <tr><td><code>setLabel/clearLabel</code></td><td>текст-метка над объектом</td></tr>
                                <tr><td><code>spawnNpc(модель,опции)</code></td><td>создать NPC</td></tr>
                                <tr><td><code>spawnParticles(тип,...)</code></td><td>частицы</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="pin" size={17} /> game.self — объект-носитель скрипта</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>ref</code> / <code>position</code></td><td>адрес и позиция объекта</td></tr>
                                <tr><td><code>onClick(fn)</code></td><td>клик по объекту</td></tr>
                                <tr><td><code>onTouch(fn)</code></td><td>игрок коснулся</td></tr>
                                <tr><td><code>onUntouch(fn)</code></td><td>игрок вышел из объекта</td></tr>
                                <tr><td><code>onInteract(fn,опции)</code></td><td>взаимодействие по E</td></tr>
                                <tr><td><code>move(x,y,z)</code></td><td>переместить себя</td></tr>
                                <tr><td><code>delete()</code></td><td>удалить себя</td></tr>
                                <tr><td><code>setText(t)</code></td><td>сменить текст (для GUI)</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="window" size={17} /> game.ui — счётчики и текст</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>score</code> / <code>timer</code></td><td>счётчики в углу</td></tr>
                                <tr><td><code>showText(текст,сек)</code></td><td>текст по центру</td></tr>
                                <tr><td><code>set(id,текст,опции)</code></td><td>своя метка на экране</td></tr>
                                <tr><td><code>remove(id)</code> / <code>clear()</code></td><td>убрать метку / всё</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="palette" size={17} /> game.gui — кнопки и меню</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>find(имя)</code> / <code>get(id)</code></td><td>найти элемент</td></tr>
                                <tr><td><code>update(id,patch)</code></td><td>изменить свойства</td></tr>
                                <tr><td><code>show(id)</code> / <code>hide(id)</code></td><td>показать / скрыть</td></tr>
                                <tr><td><code>onClick(id,fn)</code></td><td>клик по кнопке</td></tr>
                                <tr><td><code>onSubmit(id,fn)</code></td><td>ввод в поле завершён</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="target" size={17} /> physics, fx, constraints</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>physics.raycast(...)</code></td><td>луч — во что попал</td></tr>
                                <tr><td><code>physics.applyImpulse(...)</code></td><td>толкнуть объект</td></tr>
                                <tr><td><code>physics.explode(...)</code></td><td>взрыв</td></tr>
                                <tr><td><code>physics.passThrough(...)</code></td><td>проходимость</td></tr>
                                <tr><td><code>fx.beam(опции)</code></td><td>светящийся луч</td></tr>
                                <tr><td><code>fx.trail(ref,опции)</code></td><td>след за объектом</td></tr>
                                <tr><td><code>constraints.weld(a,b)</code></td><td>склейка</td></tr>
                                <tr><td><code>constraints.hinge(...)</code></td><td>петля</td></tr>
                                <tr><td><code>constraints.spring(...)</code></td><td>пружина</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="camera" size={17} /> camera, sound</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>camera.setFov(град)</code></td><td>угол обзора</td></tr>
                                <tr><td><code>camera.shake(сила,сек)</code></td><td>тряска</td></tr>
                                <tr><td><code>camera.cutscene(...)</code></td><td>пролёт камеры</td></tr>
                                <tr><td><code>camera.reset()</code></td><td>вернуть камеру</td></tr>
                                <tr><td><code>sound.play(id,опции)</code></td><td>проиграть звук</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="gear" size={17} /> События и таймеры</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>onTick(fn)</code></td><td>каждый кадр</td></tr>
                                <tr><td><code>onKey/onKeyUp(клавиша,fn)</code></td><td>клавиатура</td></tr>
                                <tr><td><code>onClick(fn)</code></td><td>клик в игре</td></tr>
                                <tr><td><code>after(сек,fn)</code></td><td>через N секунд</td></tr>
                                <tr><td><code>every(сек,fn)</code></td><td>каждые N секунд</td></tr>
                                <tr><td><code>cancel(id)</code></td><td>отменить таймер</td></tr>
                                <tr><td><code>tween(ref,св-ва,опции)</code></td><td>плавная анимация</td></tr>
                            </tbody>
                        </table>

                        <h4 className="docRefHead"><DocIcon name="code" size={17} /> Утилиты</h4>
                        <table className="docTable">
                            <tbody>
                                <tr><td><code>random(min,max)</code></td><td>случайное число</td></tr>
                                <tr><td><code>distance(a,b)</code></td><td>расстояние между точками</td></tr>
                                <tr><td><code>clamp(v,min,max)</code></td><td>зажать число в границах</td></tr>
                                <tr><td><code>lerp(a,b,t)</code></td><td>плавный переход a→b</td></tr>
                                <tr><td><code>log(...)</code></td><td>напечатать в консоль</td></tr>
                                <tr><td><code>broadcast/onMessage</code></td><td>сообщения между скриптами</td></tr>
                            </tbody>
                        </table>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ I — ГЛОССАРИЙ
    // ════════════════════════════════════════════════════
    {
        id: 'glossary',
        icon: 'glossary',
        title: 'Глоссарий',
        summary: 'Словарик: все непонятные слова из вики простым языком.',
        sections: [
            {
                id: 'terms',
                title: 'I1. Термины простым языком',
                body: (
                    <>
                        <p>Словарик слов, которые встречаются в вики:</p>
                        <table className="docTable">
                            <tbody>
                                <tr><td><b>Примитив</b></td><td>Простая 3D-фигура: куб, сфера, цилиндр. Главный строительный материал.</td></tr>
                                <tr><td><b>Модель</b></td><td>Готовая красивая 3D-фигура из библиотеки (дерево, машина).</td></tr>
                                <tr><td><b>Блок</b></td><td>Кубик одного размера, ровно встаёт по сетке.</td></tr>
                                <tr><td><b>Сцена</b></td><td>Весь игровой мир — всё, что ты построил.</td></tr>
                                <tr><td><b>Вьюпорт</b></td><td>Окно с 3D-сценой в центре редактора.</td></tr>
                                <tr><td><b>Гизмо</b></td><td>Цветные стрелки и кольца для перемещения объектов.</td></tr>
                                <tr><td><b>Иерархия</b></td><td>Список всех объектов игры в правой панели.</td></tr>
                                <tr><td><b>Инспектор</b></td><td>Панель со свойствами выделенного объекта.</td></tr>
                                <tr><td><b>Скрипт</b></td><td>Набор команд (код), который оживляет игру.</td></tr>
                                <tr><td><b>JavaScript</b></td><td>Язык программирования, на котором пишут скрипты.</td></tr>
                                <tr><td><b>Глобальный скрипт</b></td><td>Скрипт-«мозг», не привязан к объекту, запускается один раз.</td></tr>
                                <tr><td><b>Скрипт на объекте</b></td><td>Скрипт конкретного объекта, в нём работает game.self.</td></tr>
                                <tr><td><b>Переменная</b></td><td>«Коробочка с именем» — скрипт хранит в ней значение.</td></tr>
                                <tr><td><b>Функция</b></td><td>Набор команд, который выполнится, когда его позовут.</td></tr>
                                <tr><td><b>Событие</b></td><td>«Что-то случилось» — клик, касание, нажатие клавиши.</td></tr>
                                <tr><td><b>Условие (if)</b></td><td>Развилка: если что-то верно — сделай одно, иначе — другое.</td></tr>
                                <tr><td><b>Спавн</b></td><td>Появление: точка спавна — где появляется игрок; «заспавнить» — создать объект.</td></tr>
                                <tr><td><b>Респаун</b></td><td>Воскрешение игрока после смерти.</td></tr>
                                <tr><td><b>Чекпоинт</b></td><td>Контрольная точка — место, откуда игрок воскреснет.</td></tr>
                                <tr><td><b>HP</b></td><td>Здоровье игрока. При HP=0 он умирает.</td></tr>
                                <tr><td><b>ref</b></td><td>«Адрес» объекта. Команда spawn возвращает ref, по нему обращаются к объекту.</td></tr>
                                <tr><td><b>Твин</b></td><td>Плавное изменение свойства за время (плавное движение).</td></tr>
                                <tr><td><b>Тег</b></td><td>Ярлык на объекте. По тегу можно найти все помеченные объекты.</td></tr>
                                <tr><td><b>Атрибут</b></td><td>Своё значение, приклеенное к объекту (через setData).</td></tr>
                                <tr><td><b>Констрейнт</b></td><td>Связь между объектами: склейка, петля, пружина.</td></tr>
                                <tr><td><b>Эмиттер</b></td><td>Объект, создающий частицы (искры, дым, огонь).</td></tr>
                                <tr><td><b>Частицы</b></td><td>Много маленьких летящих точек для эффектов.</td></tr>
                                <tr><td><b>GUI</b></td><td>Интерфейс: кнопки, надписи, меню поверх 3D-сцены.</td></tr>
                                <tr><td><b>HUD</b></td><td>Счётчики и индикаторы поверх экрана (счёт, HP).</td></tr>
                                <tr><td><b>NPC</b></td><td>Неигровой персонаж: торговец, враг, проводник.</td></tr>
                                <tr><td><b>Триггер</b></td><td>Невидимая зона, которая что-то запускает при входе игрока.</td></tr>
                                <tr><td><b>Raycast</b></td><td>Невидимый луч — узнать, во что он попал (для стрельбы).</td></tr>
                                <tr><td><b>FOV</b></td><td>Угол обзора камеры. Больше — «шире» видно.</td></tr>
                                <tr><td><b>Катсцена</b></td><td>Видеовставка: камера сама пролетает по точкам.</td></tr>
                                <tr><td><b>Мультиплеер</b></td><td>Игра на нескольких игроков в одной комнате.</td></tr>
                                <tr><td><b>Модерация</b></td><td>Проверка игры перед публикацией в общей ленте.</td></tr>
                            </tbody>
                        </table>
                    </>
                ),
            },
        ],
    },

    // ════════════════════════════════════════════════════
    // РАЗДЕЛ J — ЧАСТЫЕ ОШИБКИ
    // ════════════════════════════════════════════════════
    {
        id: 'mistakes',
        icon: 'bug',
        title: 'Частые ошибки',
        summary: 'Что делать, если скрипт не работает или игра ведёт себя странно.',
        sections: [
            {
                id: 'script-not-working',
                title: 'J1. Скрипт не работает или не сохраняется',
                body: (
                    <>
                        <p>
                            <b>Первым делом — проверь Консоль.</b> Если в скрипте
                            опечатка, её текст появится в Консоли красным — там
                            написано, в какой строке ошибка.
                        </p>
                        <p>Самые частые опечатки:</p>
                        <ul>
                            <li>забыли точку с запятой <code>;</code> в конце команды;</li>
                            <li>
                                не закрыли скобку — открывающих и закрывающих
                                <code> ( )</code>, <code>{`{ }`}</code> должно быть
                                поровну;
                            </li>
                            <li>
                                имя команды с ошибкой: <code>game.player.teelport</code>
                                вместо <code>teleport</code>;
                            </li>
                            <li>
                                русская буква вместо английской (с виду одинаковы:
                                русская <code>с</code> и английская <code>c</code>).
                            </li>
                        </ul>
                        <p>
                            После правки скрипта — <b>сохрани игру</b>
                            (<kbd className="kbd">Ctrl</kbd>+<kbd className="kbd">S</kbd>)
                            и перезапусти Play.
                        </p>
                    </>
                ),
            },
            {
                id: 'fell-through-floor',
                title: 'J2. Объект провалился сквозь пол',
                body: (
                    <p>
                        Если объект <b>не закреплён</b> (свойство «Закреплён»
                        выключено), он падает под действием физики. Для платформ,
                        стен и декораций <b>включи «Закреплён»</b> в инспекторе —
                        тогда объект будет висеть на месте. Падать должны только те
                        объекты, которым это нужно (ящики, мячи).
                    </p>
                ),
            },
            {
                id: 'findone-null',
                title: 'J3. findOne вернул «ничего» (null) на старте',
                body: (
                    <>
                        <p>
                            Если позвать <code>game.scene.findOne(...)</code> в самой
                            первой строке скрипта — объект может быть ещё не готов,
                            и команда вернёт <code>null</code> («ничего»). Потом
                            обращение к этому <code>null</code> сломает скрипт.
                        </p>
                        <p>
                            <b>Решение:</b> ищи объект не на старте, а внутри
                            <code> onTick</code> или после небольшой задержки:
                        </p>
                        <Code>{`let door = null;
game.onTick(() => {
  // ищем дверь, пока не найдём
  if (!door) door = game.scene.findOne('Дверь');
  // ... работаем с door, когда он уже найден
});`}</Code>
                    </>
                ),
            },
            {
                id: 'ui-set-every-frame',
                title: 'J4. game.ui.set каждый кадр — игра лагает',
                body: (
                    <>
                        <p>
                            <code>onTick</code> выполняется 60 раз в секунду. Если
                            внутри него на каждом кадре звать <code>game.ui.set(...)</code>,
                            интерфейс будет обновляться слишком часто и игра начнёт
                            тормозить.
                        </p>
                        <p>
                            <b>Решение:</b> обновляй интерфейс только когда значение
                            реально изменилось:
                        </p>
                        <Code>{`let lastScore = -1;
game.onTick(() => {
  const s = game.ui.score || 0;
  if (s !== lastScore) {        // значение изменилось?
    game.ui.set('hud', 'Счёт: ' + s);
    lastScore = s;
  }
});`}</Code>
                    </>
                ),
            },
            {
                id: 'other-mistakes',
                title: 'J5. Прочие типичные грабли',
                body: (
                    <ul>
                        <li>
                            <b>Враг идёт сквозь стены</b> — проверь, что у стен
                            включено «Столкновение».
                        </li>
                        <li>
                            <b>Звук не играет</b> — проверь громкость
                            (<code>volume</code>) и что звук загружен. Не запускай
                            длинный звук в самом начале — это тормозит старт.
                        </li>
                        <li>
                            <b>Кнопка не нажимается</b> — проверь, что на неё повешен
                            <code> game.gui.onClick(...)</code> с правильным id,
                            и что у элемента правильное имя.
                        </li>
                        <li>
                            <b>Объект не двигается твином</b> — у твина свойство
                            должно быть числом (<code>{`{ y: 10 }`}</code>), а первым
                            аргументом — настоящий <code>ref</code> объекта.
                        </li>
                        <li>
                            <b>Скрипт на объекте, но game.self пустой</b> — значит
                            скрипт не привязан. Выдели объект и пересоздай скрипт
                            на нём, либо укажи носителя в настройках скрипта.
                        </li>
                        <li>
                            <b>Игрок застрял в стене</b> — не делай стену твёрдой,
                            пока игрок внутри. Используй <code>passThrough</code>
                            аккуратно.
                        </li>
                    </ul>
                ),
            },
        ],
    },
];
