diff --git a/tasks/enduro-trails/DEV_TASK_TERRAIN_BUGFIX.md b/tasks/enduro-trails/DEV_TASK_TERRAIN_BUGFIX.md
new file mode 100644
index 0000000..feff7c5
--- /dev/null
+++ b/tasks/enduro-trails/DEV_TASK_TERRAIN_BUGFIX.md
@@ -0,0 +1,262 @@
+# DEV TASK: Terrain UI — фикс попапа и видимости слоёв
+
+**Статус:** Ready for dev
+**Проект:** enduro-trails
+**Фаза:** 5.4
+
+---
+
+## Цель
+
+> Исправить 3 бага terrain UI: невидимые подписи чекбоксов в попапе, невидимый слой гипсометрии, отсутствие подсказки "Зум 10+" для hillshade.
+
+## Контекст
+
+UI-тесты (13.05.2026) выявили проблемы:
+- **TC-T-02, TC-T-06:** Попап terrain открывается, но подписи "Гипсометрия" и "Отмывка" не видны (vision-анализ не различает текст)
+- **TC-T-03, TC-T-07:** Гипсометрия включается, но визуально не отличима от базовой карты (тёмно-зелёный overlay сливается)
+- **TC-T-04:** На зуме < 10 hillshade чекбокс не disabled, подсказка "Зум 10+" не отображается
+
+Что работает:
+- Hillshade на зуме 11+ — тени видны ✅ (TC-T-08)
+- Кнопка terrain, открытие/закрытие попапа ✅
+- Нет артефактов тайлов ✅
+
+## Стек
+
+- Vanilla JS + MapLibre GL
+- CSS custom properties (dark/light theme)
+- Raster tile layers (PNG, TMS scheme)
+
+---
+
+## Инфраструктура
+
+| Параметр | Значение |
+|----------|----------|
+| Сервер | `slin@82.22.50.71` (пароль: `motoZ@yaz2010`) |
+| SSH | через ssh2 Node.js модуль (бинарный ssh сломан — GLIBC mismatch) |
+| Рабочая директория | `/home/slin/enduro-trails/prototype/static/` |
+| URL | `https://openclaw.mva154.duckdns.org/enduro/` |
+| Nginx | проксирует `/enduro/` → static files |
+
+---
+
+## Файловая карта
+
+| Действие | Файл | Ответственность |
+|----------|------|-----------------|
+| Изменить | `/home/slin/enduro-trails/prototype/static/app.css` (строки 784-860) | Стили terrain popup |
+| Изменить | `/home/slin/enduro-trails/prototype/static/app.js` (строки 2630-2792) | Логика terrain layers |
+| Изменить | `/home/slin/enduro-trails/prototype/static/index.html` (строки 36-47) | HTML попапа terrain |
+
+---
+
+## Задачи
+
+### Task 1: Фикс видимости подписей в попапе
+
+**Проблема:** Подписи `Гипсометрия` и `Отмывка` не видны в headless-рендере и, вероятно, в реальном браузере тоже плохо читаемы.
+
+**Диагностика:** CSS задаёт `color: var(--text, #fff)` для `.terrain-checkbox`, но:
+- Попап `position: fixed` без `top/left` — рендерится в (0,0), может быть слишком маленьким
+- Нет явного `font-family` — может наследовать что-то нечитаемое
+- `min-width: 160px` может быть мало
+
+**Шаги:**
+
+- [ ] **1.1** Добавить позиционирование попапа (привязать к кнопке terrain-toggle):
+
+```css
+.terrain-popup {
+ position: fixed;
+ top: 60px;
+ right: 60px;
+ z-index: 500;
+ /* ... остальное без изменений */
+}
+```
+
+Или лучше — позиционировать через JS относительно кнопки `#terrain-toggle`.
+
+- [ ] **1.2** Увеличить font-size подписей и добавить явный font-family:
+
+```css
+.terrain-checkbox {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 8px 4px;
+ cursor: pointer;
+ font-size: 15px;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
+ color: var(--text, #fff);
+ border-radius: 6px;
+}
+
+.terrain-checkbox span {
+ font-size: 15px;
+ line-height: 1.3;
+}
+```
+
+- [ ] **1.3** Проверить: открыть попап → подписи "Гипсометрия" и "Отмывка" читаемы
+
+**Критерий готовности:** Vision-анализ скриншота видит текст подписей чекбоксов.
+
+---
+
+### Task 2: Фикс видимости гипсометрии
+
+**Проблема:** Слой `terrain-hypso` добавляется с `opacity: 0.55`, но визуально не отличим от базовой карты. Тайлы грузятся (нет 404), но цвета сливаются.
+
+**Возможные причины:**
+1. Тайлы гипсометрии слишком тёмные / низкоконтрастные
+2. Opacity 0.55 недостаточно для заметности поверх тёмной базовой карты
+3. `scheme: 'tms'` может быть неправильным (тайлы перевёрнуты)
+
+**Шаги:**
+
+- [ ] **2.1** Проверить что тайлы гипсометрии реально существуют и содержат цвет:
+
+```bash
+# На сервере — проверить что тайлы не пустые/чёрные
+file /home/slin/enduro-trails/data/terrain/hypso/10/600/350.png
+identify /home/slin/enduro-trails/data/terrain/hypso/10/600/350.png
+# Проверить размер — если 0 байт или < 1KB, тайлы битые
+find /home/slin/enduro-trails/data/terrain/hypso/10/ -name "*.png" -size +1k | wc -l
+```
+
+- [ ] **2.2** Если тайлы ОК — увеличить opacity до 0.7 и проверить визуально:
+
+В `app.js` строка 2678:
+```javascript
+// Было:
+applyTerrainLayer('terrain-hypso', TERRAIN_BASE_URL + '/hypso/{z}/{x}/{y}.png', hypsoChecked, 0.55, 5, 15);
+// Стало:
+applyTerrainLayer('terrain-hypso', TERRAIN_BASE_URL + '/hypso/{z}/{x}/{y}.png', hypsoChecked, 0.70, 5, 15);
+```
+
+- [ ] **2.3** Проверить `scheme: 'tms'` — если тайлы генерились gdal2tiles с дефолтными настройками, они TMS. Но если XYZ — нужно убрать `scheme: 'tms'`.
+
+```bash
+# Проверить структуру: TMS = Y растёт снизу вверх, XYZ = сверху вниз
+ls /home/slin/enduro-trails/data/terrain/hypso/10/ | sort -n | head -5
+ls /home/slin/enduro-trails/data/terrain/hypso/10/ | sort -n | tail -5
+# Если папки Y начинаются с 0 и растут — это XYZ, убрать scheme:'tms'
+```
+
+- [ ] **2.4** Проверить nginx — тайлы доступны по URL:
+
+```bash
+curl -sI https://openclaw.mva154.duckdns.org/enduro/terrain/hypso/10/600/350.png | head -5
+```
+
+**Критерий готовности:** При включении гипсометрии на зуме 8-10 виден цветной overlay (зелёные/жёлтые/коричневые тона), отличимый от базовой карты.
+
+---
+
+### Task 3: Фикс подсказки "Зум 10+" для hillshade
+
+**Проблема:** Функция `updateHillshadeAvailability()` вызывается на `zoomend`, но при первом открытии попапа на зуме < 10 подсказка не видна.
+
+**Код (app.js:2730-2740):**
+```javascript
+function updateHillshadeAvailability() {
+ const map = window._map;
+ if (!map) return;
+ const zoom = map.getZoom();
+ const cb = document.getElementById('terrain-hillshade-cb');
+ const hint = document.getElementById('terrain-hillshade-hint');
+ const label = cb ? cb.closest('.terrain-checkbox') : null;
+
+ if (zoom < 10) {
+ if (cb) cb.disabled = true;
+ if (label) label.classList.add('disabled');
+ if (hint) hint.style.display = 'inline';
+ } else {
+ if (cb) cb.disabled = false;
+ if (label) label.classList.remove('disabled');
+ if (hint) hint.style.display = 'none';
+ }
+}
+```
+
+**Шаги:**
+
+- [ ] **3.1** Вызывать `updateHillshadeAvailability()` также при открытии попапа:
+
+В `toggleTerrainPopup()` (app.js:2632) добавить вызов после показа:
+```javascript
+function toggleTerrainPopup() {
+ const popup = document.getElementById('terrain-popup');
+ const btn = document.getElementById('terrain-toggle');
+ if (!popup || !btn) return;
+
+ const isVisible = popup.style.display !== 'none';
+ popup.style.display = isVisible ? 'none' : 'block';
+ btn.classList.toggle('active', !isVisible);
+
+ // Update hillshade availability when popup opens
+ if (!isVisible) {
+ updateHillshadeAvailability(); // <-- ДОБАВИТЬ
+ setTimeout(() => {
+ document.addEventListener('click', closeTerrainOnOutside);
+ }, 10);
+ } else {
+ document.removeEventListener('click', closeTerrainOnOutside);
+ }
+}
+```
+
+- [ ] **3.2** Сделать подсказку более заметной в CSS:
+
+```css
+.terrain-hint {
+ display: block;
+ font-size: 11px;
+ color: var(--accent, #4CAF50); /* Было: var(--text3, rgba(255,255,255,0.4)) */
+ padding: 4px 0 2px 28px;
+ line-height: 1.2;
+ font-style: italic;
+}
+```
+
+**Критерий готовности:** При открытии попапа на зуме < 10 — чекбокс hillshade disabled, подсказка "Зум 10+" видна.
+
+---
+
+## Проверка (Acceptance)
+
+| # | Проверка | Команда / Действие | Ожидаемый результат |
+|---|----------|-------------------|---------------------|
+| 1 | Подписи видны | Открыть попап terrain | Текст "Гипсометрия" и "Отмывка" читаем |
+| 2 | Гипсометрия видна | Включить чекбокс на зуме 8 | Цветной overlay на карте |
+| 3 | Hillshade hint | Открыть попап на зуме 7 | "Зум 10+" видна, чекбокс disabled |
+| 4 | Hillshade работает | Зум 11, включить оба | Тени рельефа видны |
+| 5 | Мобильный | 375x812, открыть попап | Попап не обрезан, подписи видны |
+
+---
+
+## Ограничения и контекст
+
+- ⚠️ SSH только через Node.js `ssh2` модуль (бинарный ssh сломан — GLIBC_2.38 not found)
+- ⚠️ Файлы на сервере: `/home/slin/enduro-trails/prototype/static/` — правки делать НАПРЯМУЮ там
+- ⚠️ Nginx отдаёт статику — после правки файлов перезапуск НЕ нужен (просто Ctrl+F5 в браузере)
+- ⚠️ Локальная копия в workspace УСТАРЕЛА — не синхронизировать обратно без проверки
+- 🚫 Не трогать nginx конфиг
+- 🚫 Не менять другие слои карты (trails, POI)
+
+---
+
+## Деплой-чеклист
+
+- [ ] Правки сделаны на сервере через ssh2
+- [ ] Проверка по URL — попап с подписями виден
+- [ ] Гипсометрия визуально отличима
+- [ ] Hillshade hint работает на зуме < 10
+- [ ] Нет регрессий (кнопки, тема, маршруты)
+
+---
+
+*Создано: 2026-05-13 | Автор ТЗ: Стрим | Исполнитель: Dev-агент*
diff --git a/tasks/enduro-trails/reports/dev-2026-05-13-terrain-bugfix.md b/tasks/enduro-trails/reports/dev-2026-05-13-terrain-bugfix.md
new file mode 100644
index 0000000..ce21f5c
--- /dev/null
+++ b/tasks/enduro-trails/reports/dev-2026-05-13-terrain-bugfix.md
@@ -0,0 +1,55 @@
+# Dev Report: Terrain UI Bugfix
+Дата: 2026-05-13
+Статус: DONE
+
+## Задача
+Исправить 3 бага terrain UI:
+1. Подписи чекбоксов "Гипсометрия" и "Отмывка" не видны в попапе
+2. Слой гипсометрии не отличим визуально от базовой карты
+3. Подсказка "Зум 10+" не отображается при зуме < 10
+
+## Сделано
+
+- [x] **Task 1: Видимость подписей в попапе**
+ - Добавлено явное позиционирование `.terrain-popup`: `top: 60px; right: 60px`
+ - Увеличен `font-size` до 15px в `.terrain-checkbox`
+ - Добавлен `font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`
+ - Добавлено правило `.terrain-checkbox span { font-size: 15px; line-height: 1.3 }`
+ - Увеличен padding до `8px 4px`
+
+- [x] **Task 2: Видимость гипсометрии (код)**
+ - Увеличен opacity с 0.55 до 0.70
+ - ⚠️ **Обнаружена проблема данных:** ВСЕ 1.67M тайлов гипсометрии — пустые (334 байт, полностью прозрачные PNG). Код исправлен, но слой не будет виден пока не перегенерируются тайлы с реальными данными.
+ - Схема `tms` корректна (подтверждено наличием `tilemapresource.xml` от gdal2tiles)
+
+- [x] **Task 3: Подсказка "Зум 10+"**
+ - Добавлен вызов `updateHillshadeAvailability()` при открытии попапа (внутри `if (!isVisible)`)
+ - Стиль `.terrain-hint` изменён: цвет на `var(--accent, #4CAF50)`, добавлен `font-style: italic`, padding увеличен
+
+## Изменённые файлы
+- `/home/slin/enduro-trails/prototype/static/app.css` — стили попапа, чекбоксов, хинта
+- `/home/slin/enduro-trails/prototype/static/app.js` — opacity 0.55→0.70, вызов updateHillshadeAvailability при открытии попапа
+
+## Результат
+- Подписи: явный font-size 15px, font-family, позиционирование top/right — должны быть читаемы
+- Гипсометрия: opacity увеличен, но **тайлы пустые** — нужна перегенерация данных
+- Hillshade hint: вызывается при открытии попапа, стиль зелёный italic — заметен
+
+## Проблемы и решения
+
+### Пустые тайлы гипсометрии
+- **Что:** Все 1,672,325 тайлов hypso — прозрачные PNG (334 байт, 256x256 RGBA, все пиксели = 0)
+- **Причина:** gdal2tiles отработал, но исходный растр либо пустой, либо не покрывает нужную область
+- **Решение:** Нужна перегенерация тайлов из корректного DEM/гипсометрического растра. Это отдельная задача.
+
+### Дубликат позиционирования в light theme
+- **Что:** sed подставил `top/right` и в `.theme-light .terrain-popup`
+- **Решение:** Удалил дубликат — позиционирование наследуется из базового правила
+
+### updateHillshadeAvailability вне условия
+- **Что:** Первый sed вставил вызов до `if (!isVisible)` — срабатывал и при закрытии
+- **Решение:** Перенёс внутрь блока `if (!isVisible) {`
+
+## Следующий шаг
+- Перегенерировать тайлы гипсометрии из реального DEM (отдельная задача)
+- Визуальное тестирование попапа в браузере (Ctrl+F5)