Compare commits

...

6 Commits
main ... pages

4 changed files with 1301 additions and 0 deletions

173
AGENTS.md Normal file
View File

@ -0,0 +1,173 @@
<!-- vibe42-agents-version: v3-guided-2026-06-01 -->
# Vibe42 — учебная песочница для лендингов
Workspace юзера `Elena_Tsaai`. Это **учебная среда**, где обычные люди (не разработчики) пробуют сделать свой первый сайт.
---
## 🎯 ТВОЯ РОЛЬ
Ты — **гид и помощник**, а не слепой исполнитель. Цель сессии — чтобы юзер вышел с:
1. **рабочим лендингом**, опубликованным по адресу `https://pages.git.vibe42.kz/Elena_Tsaai/<repo>/`,
2. ощущением «это было легко» — без серверов, БД, токенов, конфигов.
Юзер не разработчик. Ему важен **результат, который видно в браузере**, а не код.
---
## 🗺 СЦЕНАРИЙ ПЕРВОГО ЗАХОДА (юзер только зашёл, ещё ничего нет)
1. Поздоровайся коротко: «Привет! Тут за 10 минут собираем лендинг и публикуем его в интернете. О чём хочешь сделать?»
2. Если он не знает — предложи **4 конкретных идеи** (выбирай близкие к нему, не абстрактные):
- Промо хобби (фотография / музыка / спорт)
- Резюме / personal page с контактами
- Афиша мероприятия (концерт, день рождения, мастер-класс)
- Меню заведения / прайс услуг
- Лендинг продукта или будущего проекта (waitlist)
3. Уточни **2 короткие детали**: стиль (тёмный/светлый/яркий) и главную цель (рассказать / собрать заявку / показать работы).
4. Сразу делай `./new-project <name>` и собирай страницу. Не спрашивай разрешения на каждый шаг.
---
## 💬 ЕСЛИ ЮЗЕР ОТВЕЧАЕТ РАСПЛЫВЧАТО
Юзер говорит «сделай что-нибудь» / «ну хз» / «сюрприз» → **не делай ничего абстрактного**.
Скажи: «Давай определимся, я задам 3 коротких вопроса:
1. Это для тебя лично, для проекта/бизнеса, или для события?
2. Главная цель — рассказать о чём-то / собрать заявку / показать портфолио?
3. Любимое настроение — строгое тёмное, лёгкое светлое, яркое цветное?»
После ответов **сразу** предложи 2 конкретных варианта названия+структуры. Дай выбрать и иди делать.
---
## 🚫 ЕСЛИ ЮЗЕР ХОЧЕТ СЛОЖНОЕ — ПЕРЕФОРМУЛИРУЙ В ЛЕНДИНГ
| Запрос | Что делаем вместо |
|--------|-------------------|
| «магазин с корзиной» | лендинг с товарами + кнопка «купить» = ссылка на WhatsApp / Telegram |
| «соцсеть» | лендинг будущего проекта + waitlist-форма (Formspree / Getform) |
| «блог с админкой» | personal-page + ссылки на статьи в Telegram/Medium |
| «приложение для записи» | лендинг услуги + ссылка на Calendly / WhatsApp |
| «сайт с входом юзеров» | публичный лендинг без логина (нам логин не нужен) |
| «бот в Telegram» | лендинг с описанием бота + кнопка `t.me/...` |
**Не говори «это невозможно».** Скажи: «У нас песочница только для статических сайтов. Давай сделаем лендинг, который покажет твою идею — а кнопки/формы свяжем с готовыми сервисами (WhatsApp, Telegram, Formspree)». Юзер счастлив, результат за 15 минут.
---
## 📐 ШАБЛОНЫ СТРАНИЦ (выбирай под идею юзера)
### A — Промо продукта/услуги
**Секции:** Hero (заголовок + подзаголовок + CTA-кнопка) → 3-4 преимущества (иконка emoji + текст) → социальное доказательство (отзыв или цифра) → CTA (кнопка/телефон/мессенджер).
### B — Personal / резюме
**Секции:** Hero (фото-аватарка + имя + одна фраза «кто я») → О себе (1-2 абзаца) → 3-5 карточек проектов/опыта → Контакты (email, telegram, github как ссылки-кнопки).
### C — Афиша мероприятия
**Секции:** Hero (название + дата + место крупно) → Программа (список с временем) → Локация (картинка-placeholder + адрес) → Регистрация (форма Formspree или контакт).
### D — Меню / прайс
**Секции:** Hero (название + слоган) → Меню/прайс (категории с ценами) → Контакты (телефон, адрес, часы работы, карта-картинка).
### E — Waitlist для будущего проекта
**Секции:** Hero (название проекта + одна фраза + email-форма) → 3 фичи «что будет» → FAQ (3 пункта) → CTA (та же email-форма).
Все шаблоны — **одна страница, прокрутка вниз**. Никаких роутов, ничего динамического.
---
## ⚡ РИТУАЛ ПОСЛЕ ПЕРВОГО ЗАПУСКА
Как только готов первый рабочий вариант (даже грубый):
1. **Сразу запушь:**
```bash
git add -A
git commit -m "v1"
git push origin HEAD:pages
```
2. **ОБЯЗАТЕЛЬНО** дай юзеру ссылку **жирно**:
> 🎉 Готово! Твой лендинг здесь: **https://pages.git.vibe42.kz/Elena_Tsaai/<repo>/**
3. Скажи: «Открой в новой вкладке, посмотри. Что хочешь поменять?»
4. Дальше короткие итерации: правка → push → новый URL-показ. Каждые 2-3 правки — push.
---
## ⚠️ ЖЕЛЕЗНЫЕ ПРАВИЛА (НЕ нарушать никогда)
1. **Только статика — HTML + CSS + JS в браузере.**
2. **Никакого бэкенда.** Никаких Node/Express/FastAPI/Django/PHP/Go-серверов. Никаких БД. Никакого Redis.
3. **Никакой аутентификации / OAuth / JWT.**
4. **Никакого Docker, nginx, sudo, системных настроек.**
5. **Никаких тяжёлых сборщиков** (`npm install` дерево на 500МБ). Tailwind — только через CDN.
6. **НИКОГДА `git init` в workspace root (`/workspaces/Elena_Tsaai`)** — это папка-контейнер юзера, не репозиторий.
---
## ✅ ВСЕГДА работай через `./new-project`
Если юзер сказал «сделай сайт NAME» / «создай проект NAME»:
```bash
cd /workspaces/Elena_Tsaai
./new-project NAME # создаёт repo в Gitea + клонит локально в ./NAME/
cd NAME
# теперь создавай index.html / style.css / script.js внутри ./NAME
```
`./new-project` сам создаёт repo, клонит, и копирует туда `AGENTS.md` + `design.md`.
---
## 🌐 Git и публикация
**НЕТ GitHub.** Self-hosted git: **https://git.vibe42.kz**
- Профиль юзера: https://git.vibe42.kz/Elena_Tsaai
- Pages (живые лендинги): https://pages.git.vibe42.kz/Elena_Tsaai/<repo>/
- Креды уже в `/workspaces/Elena_Tsaai/.git-credentials` — git push/clone работают без пароля
- **НЕ спрашивай юзера про GitHub URL / токен** — их не нужно
### Опубликовать лендинг
```bash
git add -A
git commit -m "site"
git push origin HEAD:pages
```
Ветка **`pages`** (Caddy её обслуживает; `gh-pages` тоже работает как fallback). Push → лендинг доступен мгновенно.
---
## 🔧 Когда что-то идёт не так
- **Pages 404** → запушь ветку `pages` снова: `git push origin HEAD:pages -f`
- **Не дёргай Gitea API типа `/repos/.../pages`, `/settings/pages`, `/deploy_keys`** — их нет
- **Не пытайся «настроить Pages через UI Gitea»** — Pages у нас работают только через push в ветку `pages`
- Запуталось — сделай новый чистый проект через `./new-project NAME-v2`, перенеси туда работающий index.html
---
## ❌ Чего НЕ делать НИКОГДА
- ❌ `git init` в workspace root
- ❌ `npm install` с прод-зависимостями (express/mongoose/pg/prisma/next/nuxt)
- ❌ Создавать `server.js` / `app.py` / `main.go` как backend
- ❌ Использовать `gh` CLI или GitHub API
- ❌ Вызывать Gitea Pages-API (его нет)
- ❌ Долгое отлаживание Pages — почти всегда решение «push HEAD:pages»
- ❌ Просить юзера ввести токен/URL/пароль — всё уже настроено
- ❌ Задавать юзеру 10 вопросов подряд (максимум 2-3 за раз)
- ❌ Показывать юзеру голый код больше 1 раза — ему важен результат, а не как написано
- ❌ Предлагать «давай сначала дизайн в Figma» — мы делаем сразу в HTML
- ❌ Говорить «это сложно» — переформулируй в простое
- ❌ Зависать в обсуждениях — сделай первый вариант грубо, потом итерируй
---
## 🎨 design.md
Рядом лежит `design.md` с готовой палитрой, типографикой и стартер-шаблоном `index.html`. **Начинай с него.** Не выдумывай новые цвета — модифицируй существующие.

110
design.md Normal file
View File

@ -0,0 +1,110 @@
<!-- vibe42-design-version: v1-2026-06-01 -->
# Design system — Vibe42 песочница
Базовые цвета и типографика для лендингов. Можно отклоняться, но начинай с этого.
## Палитра
| Token | Hex | Использование |
|-------|-----|---------------|
| `--ink` | `#0F1218` | Тёмный фон / основной текст |
| `--cyan` | `#00E5FF` | Основной акцент (кнопки, лого) |
| `--cyan-50` | `#E8FCFF` | Светлая подложка для акцентов |
| `--white` | `#FFFFFF` | Основной фон |
| `--gray-500` | `#5B6573` | Вторичный текст |
| `--gray-100` | `#F2F4F7` | Сепараторы / тонкие фоны |
## Типографика
```css
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
```
| Уровень | Размер | Вес | line-height |
|---------|--------|-----|-------------|
| h1 (hero) | 56px | 800 | 1.05 |
| h2 (section) | 36px | 700 | 1.15 |
| h3 | 22px | 700 | 1.3 |
| body | 17px | 400 | 1.6 |
| small | 14px | 400 | 1.5 |
На мобиле — h1 уменьши до 36px, h2 до 28px.
## Лейаут
- max-width контента: **1140px** (контейнер с padding по бокам)
- секция: `padding: 80px 24px` (мобила: `48px 20px`)
- gap между блоками внутри секции: `24-32px`
- border-radius: `8px` (кнопки, карточки), `16px` (большие карточки)
## Кнопки
```css
.btn-primary {
background: var(--cyan); color: var(--ink);
padding: 14px 28px; border-radius: 8px;
font-weight: 700; text-decoration: none;
display: inline-block;
}
.btn-secondary {
background: transparent; color: var(--ink);
border: 2px solid var(--ink);
padding: 12px 26px; border-radius: 8px;
}
```
## Стартер `index.html`
```html
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Мой проект</title>
<style>
:root{--ink:#0F1218;--cyan:#00E5FF;--cyan-50:#E8FCFF;--white:#fff;--gray-500:#5B6573;--gray-100:#F2F4F7}
*{box-sizing:border-box;margin:0;padding:0}
body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;color:var(--ink);background:var(--white)}
.container{max-width:1140px;margin:0 auto;padding:80px 24px}
.hero{background:var(--ink);color:var(--white)}
.hero h1{font-size:56px;font-weight:800;line-height:1.05;margin-bottom:24px}
.hero p{font-size:20px;color:#9aa3b2;max-width:600px;margin-bottom:32px}
.btn{display:inline-block;background:var(--cyan);color:var(--ink);padding:14px 28px;border-radius:8px;font-weight:700;text-decoration:none}
.btn:hover{background:#1be5ff}
.section h2{font-size:36px;font-weight:700;margin-bottom:24px}
.card{background:var(--gray-100);border-radius:16px;padding:32px;margin-bottom:16px}
@media (max-width:640px){.hero h1{font-size:36px}.section h2{font-size:28px}.container{padding:48px 20px}}
</style>
</head>
<body>
<section class="hero">
<div class="container">
<h1>Заголовок проекта</h1>
<p>Подзаголовок — пара предложений о чём это.</p>
<a class="btn" href="#section">Начать</a>
</div>
</section>
<section id="section" class="section">
<div class="container">
<h2>Секция</h2>
<div class="card">Контент карточки.</div>
<div class="card">Контент карточки.</div>
</div>
</section>
</body>
</html>
```
## Чем НЕ пользоваться
- Bootstrap, Material UI, Chakra, Ant Design — слишком тяжело и не нужно для лендинга
- Font Awesome — используй emoji (🚀 ⚡ ✨) или inline SVG
- jQuery — vanilla JS более чем достаточно
## Чем МОЖНО (если очень надо)
- **Tailwind через CDN**: `<script src="https://cdn.tailwindcss.com"></script>` — для прототипа OK
- **Lottie animations через CDN**
- **Placeholder картинки**: `https://picsum.photos/800/600`, `https://placehold.co/600x400`
- **Шрифты Google Fonts через `<link>`** в head

878
index.html Normal file
View File

@ -0,0 +1,878 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Развитие ребёнка — гид для родителей по сферам и возрастам</title>
<meta name="description" content="Оценка развития ребёнка по возрастам: физическое, когнитивное, речевое и социально-эмоциональное. Данные и подходы на основе материалов ВОЗ и ЮНИСЕФ.">
<style>
:root{
--ink:#0F1218;
--cyan:#00E5FF;
--cyan-50:#E8FCFF;
--white:#fff;
--gray-500:#5B6573;
--gray-100:#F2F4F7;
--gray-200:#E5E9F0;
/* Сферы развития */
--phys:#16A34A; --phys-bg:#E7F7EE; /* физическое */
--cogn:#7C3AED; --cogn-bg:#F1ECFE; /* когнитивное */
--lang:#E07A00; --lang-bg:#FEF3E0; /* речевое */
--socio:#DB2777; --socio-bg:#FCE8F1; /* соц-эмоц */
--amber:#FFB74D;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;color:var(--ink);background:var(--white)}
img{max-width:100%}
a{color:inherit}
.container{max-width:1140px;margin:0 auto;padding:0 24px}
section{padding:80px 0}
@media (max-width:640px){section{padding:52px 0}}
/* ---------- Hero ---------- */
.hero{background:linear-gradient(135deg,#0F1218 0%,#13202B 55%,#0B3A47 100%);color:var(--white);overflow:hidden;position:relative}
.hero::after{content:"";position:absolute;inset:0;background:radial-gradient(900px 500px at 85% -10%,rgba(0,229,255,.18),transparent 60%);pointer-events:none}
.hero-inner{position:relative;z-index:1;padding:96px 0 92px}
.hero .eyebrow{display:inline-flex;align-items:center;gap:8px;background:rgba(0,229,255,.12);border:1px solid rgba(0,229,255,.4);color:var(--cyan);font-size:14px;font-weight:600;padding:7px 14px;border-radius:999px;margin-bottom:22px}
.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;line-height:1.06;margin-bottom:22px;letter-spacing:-.01em}
.hero p.lead{font-size:clamp(18px,2.4vw,21px);color:#aab3c2;max-width:620px;margin-bottom:30px}
.hero .ctas{display:flex;flex-wrap:wrap;gap:14px}
.btn{display:inline-flex;align-items:center;gap:9px;background:var(--cyan);color:var(--ink);padding:15px 30px;border-radius:10px;font-weight:700;text-decoration:none;transition:transform .15s,box-shadow .15s}
.btn:hover{transform:translateY(-2px);box-shadow:0 12px 30px rgba(0,229,255,.28)}
.btn.ghost{background:transparent;color:#fff;border:2px solid rgba(255,255,255,.25)}
.btn.ghost:hover{border-color:var(--cyan);box-shadow:none}
.hero-stats{display:flex;flex-wrap:wrap;gap:34px;margin-top:46px}
.hero-stats .st b{display:block;font-size:30px;font-weight:800;color:var(--cyan)}
.hero-stats .st span{font-size:14px;color:#9aa3b2}
/* ---------- Section heads ---------- */
.head{max-width:760px;margin-bottom:40px}
.head .kicker{color:var(--cyan);font-weight:700;font-size:14px;letter-spacing:.08em;text-transform:uppercase}
.head h2{font-size:clamp(27px,4vw,38px);font-weight:800;line-height:1.15;margin:10px 0 14px;letter-spacing:-.01em}
.head p{color:var(--gray-500);font-size:18px}
/* ---------- Spheres ---------- */
.spheres-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:18px}
.sphere-card{border-radius:16px;padding:26px 24px;border:1px solid var(--gray-200)}
.sphere-card .ico{width:46px;height:46px;border-radius:12px;display:grid;place-items:center;font-size:24px;margin-bottom:16px}
.sphere-card h3{font-size:19px;font-weight:700;margin-bottom:8px}
.sphere-card p{color:var(--gray-500);font-size:15px}
.s-phys{background:var(--phys-bg);border-color:#cdeed9}.s-phys .ico{background:#fff;color:var(--phys)}
.s-cogn{background:var(--cogn-bg);border-color:#e2d6fb}.s-cogn .ico{background:#fff;color:var(--cogn)}
.s-lang{background:var(--lang-bg);border-color:#faddb6}.s-lang .ico{background:#fff;color:var(--lang)}
.s-socio{background:var(--socio-bg);border-color:#f9cfe0}.s-socio .ico{background:#fff;color:var(--socio)}
/* ---------- Assessment tool ---------- */
.tool{background:linear-gradient(180deg,#FBFCFE,#F4F7FB)}
.tool-shell{background:var(--white);border:1px solid var(--gray-200);border-radius:20px;overflow:hidden;box-shadow:0 30px 60px -30px rgba(15,18,24,.18)}
.tool-top{padding:26px 28px 18px;border-bottom:1px solid var(--gray-100)}
.tool-top .lbl{font-size:14px;font-weight:700;color:var(--gray-500);text-transform:uppercase;letter-spacing:.06em;margin-bottom:14px}
.age-tabs{display:flex;flex-wrap:wrap;gap:8px}
.age-tab{border:1.5px solid var(--gray-200);background:#fff;color:var(--ink);padding:9px 15px;border-radius:999px;font-size:14.5px;font-weight:600;cursor:pointer;transition:.15s;font-family:inherit}
.age-tab:hover{border-color:#9fb0c4}
.age-tab.active{background:var(--ink);color:#fff;border-color:var(--ink)}
.tool-body{display:grid;grid-template-columns:280px 1fr}
@media (max-width:860px){.tool-body{grid-template-columns:1fr}}
.progress-side{background:#FAFBFD;padding:26px 24px;border-right:1px solid var(--gray-100)}
@media (max-width:860px){.progress-side{border-right:none;border-bottom:1px solid var(--gray-100)}}
.progress-side h4{font-size:15px;font-weight:700;margin-bottom:6px}
.progress-side .child-age{font-size:13px;color:var(--gray-500);margin-bottom:18px}
.ring-wrap{display:flex;align-items:center;gap:18px;margin-bottom:18px}
.ring{--p:0;--c:var(--cyan);width:84px;height:84px;border-radius:50%;background:conic-gradient(var(--c) calc(var(--p)*1%),#E5E9F0 0);display:grid;place-items:center;flex:none}
.ring::before{content:"";position:absolute;width:62px;height:62px;border-radius:50%;background:#FAFBFD}
.ring span{position:relative;font-weight:800;font-size:20px}
.ring-text b{font-size:16px;display:block}.ring-text span{font-size:13px;color:var(--gray-500)}
.per-sphere{display:flex;flex-direction:column;gap:11px}
.per-sphere .ps{font-size:13.5px}
.per-sphere .ps .top{display:flex;justify-content:space-between;gap:8px;margin-bottom:4px}
.per-sphere .ps .top b{font-weight:600}
.per-sphere .ps .bar{height:7px;border-radius:99px;background:var(--gray-200);overflow:hidden}
.per-sphere .ps .bar i{display:block;height:100%;width:0;border-radius:99px;transition:width .4s ease}
.disclaimer{margin-top:18px;font-size:12.5px;color:var(--gray-500);background:var(--cyan-50);border-radius:10px;padding:11px 13px;line-height:1.45}
.milestones{padding:24px 26px 30px}
.milestones .sphere-block{margin-bottom:24px}
.milestones .sphere-block:last-child{margin-bottom:0}
.sb-head{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.sb-head .dot{width:11px;height:11px;border-radius:50%}
.sb-head h3{font-size:17px;font-weight:700}
.sb-head .cnt{margin-left:auto;font-size:13px;color:var(--gray-500);font-weight:600}
.mlist{list-style:none}
.mlist li{display:flex;align-items:flex-start;gap:12px;padding:11px 12px;border-radius:10px;cursor:pointer;transition:background .12s;font-size:15.5px;line-height:1.45}
.mlist li:hover{background:var(--gray-100)}
.mlist li .box{flex:none;width:22px;height:22px;border-radius:6px;border:2px solid var(--gray-200);margin-top:1px;display:grid;place-items:center;transition:.15s}
.mlist li.done .box{background:var(--ink);border-color:var(--ink)}
.mlist li.done .box::after{content:"✓";color:#fff;font-size:13px;font-weight:800}
.mlist li.done .txt{color:var(--gray-500)}
.mlist li.done .txt b{text-decoration:line-through;color:var(--gray-500)}
.mlist li .txt b{font-weight:600}
.mlist li .txt small{display:block;color:var(--gray-500);font-size:13px;margin-top:1px}
/* ---------- Nurturing care ---------- */
.nurturing{background:var(--ink);color:#fff}
.nurturing .head .kicker{color:var(--cyan)}
.nurturing .head p{color:#9aa3b2}
.nc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:16px}
.nc-card{background:#1A212B;border:1px solid #283142;border-radius:16px;padding:24px}
.nc-card .num{width:38px;height:38px;border-radius:10px;background:rgba(0,229,255,.14);color:var(--cyan);display:grid;place-items:center;font-weight:800;margin-bottom:14px}
.nc-card h3{font-size:18px;margin-bottom:8px}
.nc-card p{color:#9aa3b2;font-size:14.5px}
/* ---------- Red flags ---------- */
.flags{background:#FFF8F6}
.flags .head .kicker{color:#D4441E}
.flags-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px}
.flag-card{background:#fff;border:1px solid #f3d8cf;border-left:4px solid #D4441E;border-radius:12px;padding:18px 20px}
.flag-card b{display:block;font-size:15px;margin-bottom:5px;color:#B23A18}
.flag-card span{font-size:14px;color:var(--gray-500)}
.flags-note{margin-top:22px;background:#fff;border:1px solid #f3d8cf;border-radius:12px;padding:18px 22px;display:flex;gap:14px;align-items:flex-start}
.flags-note .ic{font-size:22px;flex:none}
.flags-note p{font-size:15px;color:var(--gray-500)}
.flags-note p b{color:var(--ink)}
/* ---------- Tips ---------- */
.tips-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px}
.tip{background:var(--gray-100);border-radius:16px;padding:26px}
.tip .ico{font-size:26px;margin-bottom:12px}
.tip h3{font-size:18px;font-weight:700;margin-bottom:8px}
.tip p{color:var(--gray-500);font-size:15px}
/* ---------- Sources ---------- */
.sources{background:var(--gray-100)}
.src-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px}
.src{background:#fff;border:1px solid var(--gray-200);border-radius:12px;padding:18px 20px}
.src .org{display:inline-block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:3px 9px;border-radius:6px;margin-bottom:10px}
.src.who .org{background:var(--cyan-50);color:#0B7C8C}
.src.unicef .org{background:#FDE7EF;color:#B23A7A}
.src h4{font-size:16px;font-weight:700;margin-bottom:6px}
.src p{font-size:14px;color:var(--gray-500);margin-bottom:10px}
.src a{font-size:14px;font-weight:600;color:#1a6fb0;text-decoration:none}
.src a:hover{text-decoration:underline}
.src-note{margin-top:20px;font-size:13.5px;color:var(--gray-500);max-width:820px}
/* ---------- Footer ---------- */
footer{background:var(--ink);color:#9aa3b2;padding:42px 0 50px;font-size:14px}
footer .fwrap{display:flex;flex-wrap:wrap;gap:16px;justify-content:space-between;align-items:center}
footer a{color:var(--cyan);text-decoration:none;font-weight:600}
/* nav */
.nav{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.85);backdrop-filter:blur(10px);border-bottom:1px solid var(--gray-200)}
.nav-inner{display:flex;align-items:center;justify-content:space-between;height:62px}
.nav .brand{font-weight:800;font-size:17px;display:flex;align-items:center;gap:9px}
.nav .brand .b-ico{width:30px;height:30px;border-radius:8px;background:var(--ink);color:var(--cyan);display:grid;place-items:center;font-size:17px}
.nav .links{display:flex;gap:22px}
.nav .links a{text-decoration:none;font-size:15px;font-weight:600;color:var(--gray-500)}
.nav .links a:hover{color:var(--ink)}
@media (max-width:720px){.nav .links{display:none}}
/* ---------- Results / recommendations ---------- */
.tool-results{border-top:1px solid var(--gray-100);padding:26px 28px 30px;background:#FBFCFE}
.res-empty{color:var(--gray-500);font-size:15px;display:flex;align-items:center;gap:10px;background:var(--gray-100);border-radius:12px;padding:16px 18px}
.res-status{display:flex;align-items:center;gap:14px;padding:16px 18px;border-radius:12px;margin-bottom:20px}
.res-status .badge{width:46px;height:46px;border-radius:12px;display:grid;place-items:center;font-size:24px;flex:none}
.res-status h3{font-size:18px;font-weight:700;margin-bottom:3px}
.res-status p{font-size:14.5px;color:var(--gray-500)}
.st-ok{background:var(--phys-bg)}.st-ok .badge{background:#fff;color:var(--phys)}
.st-watch{background:var(--lang-bg)}.st-watch .badge{background:#fff;color:var(--lang)}
.st-lag{background:#FFEDE7}.st-lag .badge{background:#fff;color:#D4441E}
.res-sub{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--gray-500);margin:6px 0 12px}
.rec-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:14px}
.rec-card{background:#fff;border:1px solid var(--gray-200);border-radius:14px;padding:20px 22px;border-top:4px solid var(--gray-200)}
.rec-card h4{font-size:16px;font-weight:700;margin-bottom:6px;display:flex;align-items:center;gap:8px}
.rec-card .rc-pill{font-size:12px;font-weight:700;padding:3px 9px;border-radius:6px;margin-bottom:12px;display:inline-block}
.rc-lag{background:#FFEDE7;color:#B23A18}
.rc-watch{background:var(--lang-bg);color:var(--lang)}
.rec-card ul{list-style:none}
.rec-card ul li{position:relative;padding:7px 0 7px 22px;font-size:14.5px;color:var(--gray-500);line-height:1.45;border-bottom:1px solid var(--gray-100)}
.rec-card ul li:last-child{border-bottom:none}
.rec-card ul li::before{content:"→";position:absolute;left:0;top:7px;font-weight:700;color:var(--ink)}
.res-doctor{margin-top:18px;background:#FFF8F6;border:1px solid #f3d8cf;border-left:4px solid #D4441E;border-radius:12px;padding:16px 20px;display:flex;gap:14px;align-items:flex-start}
.res-doctor .ic{font-size:22px;flex:none}
.res-doctor p{font-size:14.5px;color:var(--gray-500)}
.res-doctor p b{color:#B23A18}
.res-base{margin-top:16px;background:var(--cyan-50);border:1px solid #c8eef3;border-radius:12px;padding:16px 20px}
.res-base h4{font-size:15px;font-weight:700;margin-bottom:10px}
.res-base ul{list-style:none;display:grid;gap:7px}
.res-base ul li{position:relative;padding-left:24px;font-size:14px;color:var(--gray-500);line-height:1.45}
.res-base ul li::before{content:"✓";position:absolute;left:0;top:0;color:#0B7C8C;font-weight:800}
.lag-hint{display:none;margin-top:14px;font-size:13px;font-weight:700;color:#B23A18;background:#FFEDE7;border-radius:8px;padding:8px 12px;text-align:center}
.lag-hint.show{display:block}
/* ---------- Collect panel ---------- */
.tool-collect{border-top:1px solid var(--gray-100);padding:26px 28px 30px;background:#fff}
.collect-head{display:flex;gap:16px;margin-bottom:18px}
.collect-head .ch-ic{width:46px;height:46px;border-radius:12px;background:var(--cyan-50);display:grid;place-items:center;font-size:24px;flex:none}
.collect-head h3{font-size:18px;font-weight:700;margin-bottom:4px}
.collect-head p{font-size:14px;color:var(--gray-500);max-width:640px}
.collect-form{display:grid;gap:14px;max-width:560px}
.cfield{display:grid;gap:6px;font-size:14px;font-weight:600}
.cfield small{font-weight:400;color:var(--gray-500)}
.cfield input{padding:11px 13px;border:1.5px solid var(--gray-200);border-radius:9px;font-size:15px;font-family:inherit}
.cfield input:focus{outline:none;border-color:var(--cyan)}
.cconsent{display:flex;gap:10px;align-items:flex-start;font-size:14px;color:var(--gray-500);cursor:pointer}
.cconsent input{margin-top:2px;width:18px;height:18px;flex:none;cursor:pointer}
.collect-actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.collect-actions .btn{cursor:pointer;border:none;font-family:inherit;font-size:15px}
.cmsg{font-size:14px;font-weight:600;color:var(--gray-500);min-height:18px}
.cmsg.ok{color:var(--phys)}
.cmsg.err{color:#D4441E}
.collect-priv{font-size:12.5px;color:var(--gray-500);margin-top:2px;line-height:1.5}
.collect-off{background:var(--gray-100);border-radius:12px;padding:16px 18px;font-size:14.5px;color:var(--gray-500);line-height:1.5}
.collect-off b{color:var(--ink)}
</style>
</head>
<body>
<nav class="nav"><div class="container nav-inner">
<div class="brand"><span class="b-ico"></span> Развитие ребёнка</div>
<div class="links">
<a href="#spheres">Сферы</a>
<a href="#tool">Оценка</a>
<a href="#care">Уход</a>
<a href="#flags">Тревоги</a>
<a href="#sources">Источники</a>
</div>
</div></nav>
<!-- HERO -->
<header class="hero">
<div class="container hero-inner">
<span class="eyebrow">🌟 Гид для родителей · на основе ВОЗ и ЮНИСЕФ</span>
<h1>Развитие ребёнка<br>по возрастам и сферам</h1>
<p class="lead">Понятный инструмент, чтобы оценить, как развивается ваш ребёнок: физически, когнитивно, речево и социально-эмоционально. С рекомендациями по уходу и подсказками, когда обратиться к специалисту.</p>
<div class="ctas">
<a class="btn" href="#tool">Проверить развитие →</a>
<a class="btn ghost" href="#care">Советы родителям</a>
</div>
<div class="hero-stats">
<div class="st"><b>6</b><span>возрастных периодов</span></div>
<div class="st"><b>4</b><span>сферы развития</span></div>
<div class="st"><b>~100</b><span>вех развития</span></div>
<div class="st"><b>5</b><span>условий заботы ВОЗ/ЮНИСЕФ</span></div>
</div>
</div>
</header>
<!-- SPHERES -->
<section id="spheres">
<div class="container">
<div class="head">
<span class="kicker">4 сферы развития</span>
<h2>Развитие оценивают сразу в четырёх направлениях</h2>
<p>ВОЗ и ЮНИСЕФ рекомендуют смотреть на ребёнка целиком, а не только на рост и вес. Все четыре сферы связаны и влияют друг на друга.</p>
</div>
<div class="spheres-grid">
<div class="sphere-card s-phys">
<div class="ico">🏃</div>
<h3>Физическое и моторное</h3>
<p>Рост, вес, крупные движения (сидит, ползает, ходит) и мелкая моторика (хватает, рисует, застёгивает).</p>
</div>
<div class="sphere-card s-cogn">
<div class="ico">🧩</div>
<h3>Когнитивное</h3>
<p>Как ребёнок познаёт мир: внимание, память, причинно-следственные связи, игра, решение задач.</p>
</div>
<div class="sphere-card s-lang">
<div class="ico">💬</div>
<h3>Речевое и коммуникативное</h3>
<p>Понимание речи, лепет, первые слова и фразы, умение выразить мысль и быть понятым.</p>
</div>
<div class="sphere-card s-socio">
<div class="ico">❤️</div>
<h3>Социально-эмоциональное</h3>
<p>Привязанность, эмоции, общение со сверстниками и взрослыми, самостоятельность, эмпатия.</p>
</div>
</div>
</div>
</section>
<!-- ASSESSMENT TOOL -->
<section id="tool" class="tool">
<div class="container">
<div class="head">
<span class="kicker">Интерактивная оценка</span>
<h2>Отметьте навыки, которые уже есть у ребёнка</h2>
<p>Выберите возраст — появятся вехи развития по четырём сферам. Отмечайте освоенные навыки: инструмент покажет общий прогресс и по каждой сфере отдельно.</p>
</div>
<div class="tool-shell">
<div class="tool-top">
<div class="lbl">Возраст ребёнка</div>
<div class="age-tabs" id="ageTabs"></div>
</div>
<div class="tool-body">
<div class="progress-side">
<h4>Ваш прогресс</h4>
<div class="child-age" id="childAge">Выберите возраст</div>
<div class="ring-wrap">
<div class="ring" id="ring"><span id="ringNum">0%</span></div>
<div class="ring-text"><b id="ringDone">0 из 0</b><span>вех освоено</span></div>
</div>
<div class="per-sphere" id="perSphere"></div>
<div class="lag-hint" id="lagHint">⚠ Смотрите рекомендации ниже</div>
<div class="disclaimer">Это памятка для родителей, а не диагноз. Дети развиваются индивидуально. Если что-то беспокоит — обсудите с педиатром.</div>
</div>
<div class="milestones" id="milestones"></div>
</div>
<div class="tool-results" id="toolResults"></div>
<div class="tool-collect" id="toolCollect">
<div class="collect-head">
<div class="ch-ic">📨</div>
<div>
<h3>Отправить результат для аналитики</h3>
<p>Помогите улучшить гид — отправьте обезличенный результат оценки. Мы не собираем имена и контакты детей, только возраст и отметки навыков.</p>
</div>
</div>
<div class="collect-form" id="collectForm">
<label class="cfield">
<span>Ваш email <small>(необязательно — если хотите получить копию результата)</small></span>
<input type="email" id="cEmail" placeholder="you@example.com">
</label>
<label class="cconsent">
<input type="checkbox" id="cConsent">
<span>Я согласен(на) на анонимную обработку данных оценки развития ребёнка в образовательных и исследовательских целях.</span>
</label>
<div class="collect-actions">
<button class="btn" id="cSubmit" type="button">Отправить результат</button>
<span class="cmsg" id="cMsg"></span>
</div>
<div class="collect-priv">Данные сохраняются напрямую в Google Таблицу владельца сайта. Анализ — сводными таблицами по возрастам, сферам и статусам. Имена и контакты детей не собираются.</div>
</div>
<div class="collect-off" id="collectOff"><b>Сбор данных скоро будет подключён.</b> Владельцу сайта нужно настроить приёмник (Google Таблицу) — после этого форма станет активной.</div>
</div>
</div>
</div>
</section>
<!-- NURTURING CARE -->
<section id="care" class="nurturing">
<div class="container">
<div class="head">
<span class="kicker">Заботливый уход</span>
<h2>5 условий для здорового развития</h2>
<p>Рамка «заботливого ухода» (Nurturing Care Framework) разработана ВОЗ, ЮНИСЕФ и Всемирным банком. Это пять условий, которые нужны ребёнку с рождения.</p>
</div>
<div class="nc-grid">
<div class="nc-card"><div class="num">1</div><h3>Здоровье</h3><p>Здоровая беременность и роды, наблюдение у врача, прививки по календарю, своевременное лечение.</p></div>
<div class="nc-card"><div class="num">2</div><h3>Питание</h3><p>Грудное вскармливание до 6 месяцев исключительно и до 2 лет и дольше, полноценный прикорм, необходимые нутриенты и витамины.</p></div>
<div class="nc-card"><div class="num">3</div><h3>Безопасность и защита</h3><p>Физически безопасная среда дома, защита от насилия и пренебрежения, стабильность в семье.</p></div>
<div class="nc-card"><div class="num">4</div><h3>Отзывчивая забота</h3><p>Замечать сигналы ребёнка и отвечать на них — улыбкой, словом, объятием. Это «диалог» с малышом с рождения.</p></div>
<div class="nc-card"><div class="num">5</div><h3>Раннее обучение</h3><p>Игра, исследование, разговоры, книги и песни — окружение, которое стимулирует любопытство и развитие мозга.</p></div>
</div>
</div>
</section>
<!-- RED FLAGS -->
<section id="flags" class="flags">
<div class="container">
<div class="head">
<span class="kicker">Когда насторожиться</span>
<h2>Сигналы, при которых стоит обратиться к специалисту</h2>
<p>Это поводы для консультации с педиатром или неврологом, а не приговор. Раннее обращение помогает вовремя поддержать развитие.</p>
</div>
<div class="flags-grid">
<div class="flag-card"><b>Нет улыбки в ответ</b><span>К 2 месяцам ребёнок не улыбается, когда с ним разговаривают.</span></div>
<div class="flag-card"><b>Не держит голову</b><span>К 34 месяцам не удерживает голову, когда его держат вертикально.</span></div>
<div class="flag-card"><b>Не сидит с поддержкой</b><span>К 9 месяцам не садится даже с опорой.</span></div>
<div class="flag-card"><b>Нет лепета и указывания</b><span>К 12 месяцам не лепечет («ба-ба», «ма-ма») и не показывает пальцем.</span></div>
<div class="flag-card"><b>Нет первых слов</b><span>К 1618 месяцам не произносит ни одного осмысленного слова.</span></div>
<div class="flag-card"><b>Не ходит</b><span>К 18 месяцам не делает самостоятельные шаги.</span></div>
<div class="flag-card"><b>Нет фраз из 2 слов</b><span>К 24 месяцам не соединяет слова во фразы («дай ми»).</span></div>
<div class="flag-card"><b>Потеря навыков</b><span>Ребёнок перестал делать то, что уже умел — речь, движения, контакт.</span></div>
<div class="flag-card"><b>Слабый зрительный контакт</b><span>Не смотрит в глаза, не откликается на имя к 12 месяцам.</span></div>
</div>
<div class="flags-note">
<div class="ic">🩺</div>
<p><b>Помните:</b> дети развиваются в своём темпе, и небольшой разброс нормален. Но если навык задерживается значительно или вы заметили регресс — не ждите, обратитесь к врачу. Раннее развитие мозга максимально пластично в первые годы жизни.</p>
</div>
</div>
</section>
<!-- TIPS -->
<section id="tips">
<div class="container">
<div class="head">
<span class="kicker">Практические советы</span>
<h2>Что могут делать родители каждый день</h2>
<p>Простые действия, основанные на принципе «отзывчивой заботы» и раннего обучения — главных условиях гармоничного развития.</p>
</div>
<div class="tips-grid">
<div class="tip"><div class="ico">🗣️</div><h3>Разговаривайте с ребёнком</h3><p>С самого рождения комментируйте действия, называйте предметы. Число слов, которые слышит ребёнок, напрямую связано с развитием речи.</p></div>
<div class="tip"><div class="ico">📚</div><h3>Читайте каждый день</h3><p>Даже несколько минут чтения и рассматривания картинок развивают речь, внимание и эмоциональную связь.</p></div>
<div class="tip"><div class="ico">🤸</div><h3>Играйте и двигайтесь</h3><p>Игра — главный способ обучения. Дайте время на «животик», ползание, бег, игры с мячом и мелкую моторику.</p></div>
<div class="tip"><div class="ico">🔁</div><h3>Отвечайте на сигналы</h3><p>«Подавайте и принимайте»: улыбнулся — улыбнитесь, показал интерес — поддержите. Это формирует мозг активнее любых занятий.</p></div>
<div class="tip"><div class="ico">🥗</div><h3>Кормите по потребности</h3><p>Грудное молоко до 6 месяцев, разнообразный прикорм после. Отзывчивое кормление — по сигналам голода и сытости.</p></div>
<div class="tip"><div class="ico">😴</div><h3>Обеспечьте сон и режим</h3><p>Достаточный сон, предсказуемый режим и спокойная обстановка снижают стресс и поддерживают развитие.</p></div>
</div>
</div>
</section>
<!-- SOURCES -->
<section id="sources" class="sources">
<div class="container">
<div class="head">
<span class="kicker">Источники</span>
<h2>На чём основаны данные</h2>
<p>Материалы сайта опираются на публикуемые руководства и стандарты Всемирной организации здравоохранения и Детского фонда ООН (ЮНИСЕФ).</p>
</div>
<div class="src-list">
<div class="src who"><span class="org">ВОЗ</span><h4>Стандарты физического роста детей (WHO Child Growth Standards)</h4><p>Кривые роста, веса и окружности головы от рождения до 5 лет — основа оценки физического развития.</p><a href="https://www.who.int/tools/child-growth-standards" target="_blank" rel="noopener">who.int/tools/child-growth-standards →</a></div>
<div class="src who"><span class="org">ВОЗ</span><h4>Вехи моторного развития (Multicentre Reference Study)</h4><p>Шесть ключевых моторных вех: сидит, стоит с опорой, ползает, ходит с опорой, стоит сам, ходит сам.</p><a href="https://www.who.int/publications/i/item/924159693X" target="_blank" rel="noopener">WHO Motor Development Study →</a></div>
<div class="src who"><span class="org">ВОЗ</span><h4>Руководство по улучшению раннего развития детей</h4><p>Recommendations on interventions for ECD — рекомендации по стимуляции, отзывчивой заботе и питанию.</p><a href="https://www.who.int/publications/i/item/9789240010206" target="_blank" rel="noopener">Improving ECD guidelines →</a></div>
<div class="src unicef"><span class="org">ЮНИСЕФ</span><h4>Раннее развитие детей (Early Childhood Development)</h4><p>Подход ЮНИСЕФ к первым 1000 дням жизни и развитию детей до 8 лет через игру и заботу.</p><a href="https://www.unicef.org/early-childhood-development" target="_blank" rel="noopener">unicef.org/early-childhood-development →</a></div>
<div class="src unicef"><span class="org">ЮНИСЕФ</span><h4>Забота о развитии ребёнка (Care for Child Development)</h4><p>Пакет рекомендаций ЮНИСЕФ/ВОЗ для родителей: играй и общайся, чтобы поддержать развитие.</p><a href="https://www.unicef.org/early-childhood-development/care-for-child-development" target="_blank" rel="noopener">Care for Child Development →</a></div>
<div class="src unicef"><span class="org">ЮНИСЕФ</span><h4>Nurturing Care Framework</h4><p>Рамка заботливого ухода ВОЗ/ЮНИСЕФ/Всемирного банка — 5 условий для развития ребёнка.</p><a href="https://nurturing-care.org" target="_blank" rel="noopener">nurturing-care.org →</a></div>
</div>
<p class="src-note">Информация на сайте носит образовательный характер и не заменяет консультацию врача. Вехи развития приведены как ориентир — сроки их появления у конкретного ребёнка могут отличаться. Для индивидуальной оценки развития обращайтесь к педиатру.</p>
</div>
</section>
<footer>
<div class="container fwrap">
<div>Гид для родителей о развитии ребёнка · данные ВОЗ и ЮНИСЕФ</div>
<div>Образовательный ресурс, не медицинская консультация</div>
</div>
</footer>
<script>
/* ====== Данные по сферам и возрастам (на основе ВОЗ / ЮНИСЕФ) ====== */
const SPHERES = {
phys: {name:"Физическое и моторное", color:"var(--phys)", emoji:"🏃"},
cogn: {name:"Когнитивное", color:"var(--cogn)", emoji:"🧩"},
lang: {name:"Речевое", color:"var(--lang)", emoji:"💬"},
socio: {name:"Социально-эмоциональное",color:"var(--socio)", emoji:"❤️"}
};
const DATA = {
"06 мес": {
phys:[
["Удерживает голову","когда держат вертикально, к 34 мес"],
["Лежа на животе, приподнимает голову и грудь","~23 мес"],
["Тянется руками к предметам и тянет в рот",""],
["Переворачивается со спины на бок/живот","~46 мес"],
["Хватает предмет всей ладонью",""]
],
cogn:[
["Следит взглядом за движущимся предметом/лицом",""],
["Реагирует на звуки — поворачивает голову",""],
["Изучает предметы ртом и руками",""],
["Узнаёт лицо родителя на расстоянии",""]
],
lang:[
["Издаёт звуки — гулит («а-а», «гы»)","~23 мес"],
["Улыбается, когда с ним говорят",""],
["Поворачивается к источнику голоса",""],
["Начинает лепетать согласными","к концу периода"]
],
socio:[
["Социальная улыбка в ответ","~2 мес"],
["Успокаивается на руках у родителя",""],
["Различает знакомых и незнакомых",""],
["Издаёт разные звуки для разных потребностей",""]
]
},
"612 мес": {
phys:[
["Сидит без поддержки","~6 мес (ВОЗ)"],
["Стоит с опорой","~7,5 мес (ВОЗ)"],
["Ползает на четвереньках","~8,5 мес (ВОЗ)"],
["Ходит с поддержкой за руки","~9 мес (ВОЗ)"],
["Стоит самостоятельно","~11 мес (ВОЗ)"],
["Ходит самостоятельно","~12 мес (ВОЗ)"],
["Берёт предметы щепотью (пинцетный хват)","~910 мес"]
],
cogn:[
["Находит спрятанный на глазах предмет","понятие постоянства объекта"],
["Исследует предметы: стучит, трясёт, бросает",""],
["Подражает простым действиям",""],
["Понимает назначение предметов (расчёска, ложка)",""]
],
lang:[
["Лепечет слогами («ба-ба», «ма-ма»)",""],
["Откликается на своё имя",""],
["Понимает «нельзя»",""],
["Использует жесты: машет, показывает",""],
["Говорит первое осмысленное слово","~12 мес"]
],
socio:[
["Играет в «ку-ку»",""],
["Боится незнакомых (страхи новизны)",""],
["Тревожится при расставании с мамой",""],
["Показывает предпочтения и привязанность",""]
]
},
"12 года": {
phys:[
["Уверенно ходит сам",""],
["Бегает (несколько неуклюже)","~18 мес"],
["Поднимается по лестнице с опорой",""],
["Бьёт по мячу ногой",""],
["Строит башню из 24 кубиков",""],
["Черкает карандашом",""],
["Сам ест ложкой",""]
],
cogn:[
["Простая сюжетная игра (кормит куклу)",""],
["Показывает части тела по просьбе",""],
["Сортирует по форме в доску-вкладыш",""],
["Понимает простую причину-следствие",""]
],
lang:[
["1050 слов к 18 мес, 50+ к 2 годам",""],
["Соединяет 2 слова во фразу","~2 года"],
["Понимает простые инструкции («принеси мяч»)",""],
["Показывает на названные предметы/картинки",""]
],
socio:[
["Играет рядом с детьми (параллельная игра)",""],
["Показывает независимость («я сам!», «нет!»)",""],
["Показывает вещи, чтобы поделиться интересом",""],
["Проявляет сочувствие при чужой грусти",""]
]
},
"23 года": {
phys:[
["Хорошо бегает",""],
["Прыгает на двух ногах",""],
["Едет на трёхколёсном велосипеде (педали)","~3 года"],
["Стоит на одной ноге пару секунд",""],
["Копирует круг",""],
["Нанизывает крупные бусины",""]
],
cogn:[
["Сортирует по цвету и форме",""],
["Считает до 3, понимает «один-много»",""],
["Собирает пазл из 34 деталей",""],
["Сложная сюжетная игра (готовит, лечит)",""]
],
lang:[
["Говорит фразами из 3 слов",""],
["Знает имя и возраст",""],
["Задаёт вопросы «почему?»",""],
["Выполняет двухступенчатую инструкцию",""],
["Речь понятна ~75%"]
],
socio:[
["Подражает взрослым и сверстникам",""],
["Проявляет нежность и заботу",""],
["Учится делиться и ждать очереди (с помощью)",""],
["Начинает играть «рядом и вместе»"]
]
},
"35 лет": {
phys:[
["Прыгает на одной ноге",""],
["Ловит отскочивший мяч",""],
["Ходит по лестнице чередуя ноги",""],
["Использует ножницы",""],
["Рисует человека из 3+ частей",""],
["Сам одевается и раздевается",""]
],
cogn:[
["Считает до 10",""],
["Знает основные цвета",""],
["Понимает время: утро, скоро, вчера",""],
["Сортирует по размеру",""],
["Узнаёт некоторые буквы и цифры",""]
],
lang:[
["Рассказывает короткие истории",""],
["Использует будущее время",""],
["Речь полностью понятна",""],
["Выполняет трёхступенчатую инструкцию",""],
["Задаёт много вопросов «как», «почему»"]
],
socio:[
["Совместная игра с правилами",""],
["Есть друзья, предпочитает кого-то",""],
["Легко расстаётся с родителями",""],
["Понимает чужие чувства, проявляет заботу",""]
]
},
"67 лет": {
phys:[
["Ездит на двухколёсном велосипеде",""],
["Умеет галоп/прыжки в длину",""],
["Завязывает шнурки",""],
["Пишет разборчиво, рисует детали",""],
["Ловит маленький мяч"]
],
cogn:[
["Читает простые слова и короткие тексты",""],
["Складывает и вычитает в пределах 10",""],
["Понимает сохранение количества",""],
["Планирует и доводит дело до конца",""],
["Логически рассуждает"]
],
lang:[
["Свободно ведёт беседу",""],
["Пересказывает историю последовательно",""],
["Читает самостоятельно",""],
["Пишет простые предложения"]
],
socio:[
["Устойчивые дружбы",""],
["Соблюдает правила класса/игры",""],
["Лучше управляет эмоциями",""],
["Понимает справедливость и делится"]
]
}
};
/* ====== Рекомендации по сферам (если отстаёт) ====== */
const REC = {
phys:{
title:"Физическое и моторное",
tips:[
"Давайте больше свободного движения на полу — без ходунков и шезлонгов, которые ограничивают.",
"Для малышей — время на животике по несколько раз в день.",
"Ежедневно активная игра: ползание, лазание, бег, игры с мячом (от 1 часа для детей 15 лет, по ВОЗ).",
"Развивайте мелкую моторику: шнуровки, крупные бусины, лепка, рисование, игры с песком и водой.",
"Покажите педиатру, чтобы исключить мышечный тонус и неврологические причины."
]
},
cogn:{
title:"Когнитивное",
tips:[
"Играйте в сортировку по цвету, форме и размеру; простые пазлы и вкладыши.",
"Показывайте причинно-следственные связи: «нажмёшь — зазвенит», «упадёт — покатится».",
"Сюжетные игры развивают мышление: кормим куклу, готовим, лечим, магазин.",
"Задавайте вопросы и давайте время подумать — не торопите и не делайте за ребёнка.",
"Меньше экрана — больше реального исследования предметов руками."
]
},
lang:{
title:"Речевое",
tips:[
"Разговаривайте постоянно: комментируйте действия и называйте предметы.",
"Читайте каждый день 510 минут и обсуждайте картинки.",
"Пойте песни, учите потешки и стишки — ритм помогает освоению речи.",
"Повторяйте за ребёнком его звуки и слова, расширяя до фразы («ма-ма» → «мама пришла»).",
"Нет слов к 1,5 годам или фраз к 2 годам — обратитесь к неврологу/логопеду."
]
},
socio:{
title:"Социально-эмоциональное",
tips:[
"Отвечайте на сигналы ребёнка — улыбкой, словом, объятием («подавай-принимай»).",
"Называйте эмоции вслух: «ты злишься», «тебе обидно» — так ребёнок их понимает.",
"Организуйте общение с детьми; учите делиться и ждать очереди через игру.",
"Сохраняйте предсказуемый режим дня — стабильность снижает тревогу.",
"Будьте рядом в новых ситуациях и поддерживайте, не заставляя преодолевать страх в одиночку."
]
}
};
const BASE_TIPS = [
"Отзывчивая забота: замечайте и отвечайте на сигналы ребёнка.",
"Разговаривайте, читайте и пойте каждый день.",
"Игра — главный способ обучения ребёнка.",
"Обеспечьте полноценное питание, достаточный сон и безопасную среду.",
"Если заметили потерю навыков — сразу обратитесь к врачу."
];
/* ====== Render tool ====== */
const ageTabs = document.getElementById('ageTabs');
const milestonesEl = document.getElementById('milestones');
const perSphereEl = document.getElementById('perSphere');
const ring = document.getElementById('ring');
const ringNum = document.getElementById('ringNum');
const ringDone = document.getElementById('ringDone');
const childAge = document.getElementById('childAge');
const toolResults = document.getElementById('toolResults');
const lagHint = document.getElementById('lagHint');
const ages = Object.keys(DATA);
let currentAge = ages[0];
const checked = {}; // key -> bool
ages.forEach(age => {
const b = document.createElement('button');
b.className = 'age-tab' + (age===currentAge?' active':'');
b.textContent = age;
b.onclick = () => { currentAge = age; render(); };
ageTabs.appendChild(b);
});
function render(){
document.querySelectorAll('.age-tab').forEach(t=>{
t.classList.toggle('active', t.textContent===currentAge);
});
childAge.textContent = 'Возраст: ' + currentAge;
milestonesEl.innerHTML = '';
const block = DATA[currentAge];
let sphereTotals = [];
let total=0, done=0;
Object.keys(SPHERES).forEach(key=>{
const sp = SPHERES[key];
const items = block[key] || [];
let sDone=0;
const sBlock = document.createElement('div');
sBlock.className = 'sphere-block';
sBlock.innerHTML = `<div class="sb-head"><span class="dot" style="background:${sp.color}"></span><h3>${sp.emoji} ${sp.name}</h3><span class="cnt"></span></div>`;
const ul = document.createElement('ul');
ul.className = 'mlist';
items.forEach((it, i)=>{
const id = currentAge+'|'+key+'|'+i;
const isDone = !!checked[id];
if(isDone) sDone++;
const li = document.createElement('li');
if(isDone) li.classList.add('done');
li.innerHTML = `<span class="box"></span><span class="txt"><b>${it[0]}</b>${it[1]?'<small>'+it[1]+'</small>':''}</span>`;
li.onclick = ()=>{ checked[id]=!checked[id]; render(); };
ul.appendChild(li);
});
sBlock.querySelector('.cnt').textContent = sDone+' / '+items.length;
sBlock.appendChild(ul);
milestonesEl.appendChild(sBlock);
total += items.length; done += sDone;
sphereTotals.push({key, name:sp.name, color:sp.color, done:sDone, len:items.length});
});
// progress ring
const pct = total? Math.round(done/total*100):0;
ring.style.setProperty('--p', pct);
ringNum.textContent = pct+'%';
ringDone.textContent = done+' из '+total;
// per-sphere bars
perSphereEl.innerHTML = sphereTotals.map(s=>{
const p = s.len? Math.round(s.done/s.len*100):0;
return `<div class="ps"><div class="top"><b>${s.name}</b><span>${s.done}/${s.len}</span></div><div class="bar"><i style="width:${p}%;background:${s.color}"></i></div></div>`;
}).join('');
// ===== рекомендации по итогам оценки =====
const RANK = {ok:0, watch:1, lag:2};
const sphereStats = sphereTotals.filter(s=>s.len).map(s=>{
const p = s.done/s.len*100;
const st = p >= 70 ? 'ok' : (p >= 40 ? 'watch' : 'lag');
return {...s, p:Math.round(p), st};
});
let worst = 0;
sphereStats.forEach(s=>{ worst = Math.max(worst, RANK[s.st]); });
const worstStatus = worst===2 ? 'lag' : worst===1 ? 'watch' : 'ok';
// индикатор в боковой панели
lagHint.classList.toggle('show', done>0 && (worstStatus==='lag' || worstStatus==='watch'));
if(done === 0){
toolResults.innerHTML = `<div class="res-empty">👆 Отметьте навыки, которые уже есть у ребёнка, — здесь сразу появятся персональные рекомендации.</div>`;
return;
}
// шапка-статус
const statusMap = {
ok: {cls:'st-ok', icon:'✅', title:'Развитие идёт хорошо', text:'Большинство вех освоено. Продолжайте играть, разговаривать и поддерживать ребёнка.'},
watch: {cls:'st-watch', icon:'🟠', title:'Некоторые навыки ещё осваиваются', text:'Это нормально для возраста. Ниже — как поддержать сферы, которые развиваются медленнее.'},
lag: {cls:'st-lag', icon:'🔴', title:'Есть сферы, требующие внимания', text:'Рекомендуем целенаправленно поддержать развитие в этих направлениях. При сохранении отставания — обратитесь к специалисту.'}
};
const sm = statusMap[worstStatus];
let html = `<div class="res-status ${sm.cls}"><div class="badge">${sm.icon}</div><div><h3>${sm.title}</h3><p>${sm.text}</p></div></div>`;
// карточки рекомендаций для отстающих/осваивающихся сфер (lag -> watch)
const focus = sphereStats.filter(s=>s.st==='lag' || s.st==='watch')
.sort((a,b)=> RANK[b.st]-RANK[a.st]);
if(focus.length){
html += `<div class="res-sub">Рекомендации по сферам развития</div><div class="rec-grid">`;
focus.forEach(s=>{
const r = REC[s.key];
const pill = s.st==='lag'
? `<span class="rc-pill rc-lag">Отстаёт · ${s.p}%</span>`
: `<span class="rc-pill rc-watch">Осваивается · ${s.p}%</span>`;
const lis = r.tips.map(t=>`<li>${t}</li>`).join('');
html += `<div class="rec-card" style="border-top-color:${s.color}">
<h4>${SPHERES[s.key].emoji} ${r.title}</h4>${pill}<ul>${lis}</ul></div>`;
});
html += `</div>`;
}
// блок «когда к специалисту» — заметнее при отставании
if(worstStatus === 'lag'){
html += `<div class="res-doctor"><div class="ic">🩺</div><p><b>Когда обратиться к специалисту.</b> Если отставание сохраняется дольше 12 месяцев, есть потеря освоенных навыков, ребёнок не откликается на имя или избегает зрительного контакта — покажите его педиатру, неврологу и (при речевых задержках) логопеду. Раннее развитие мозга максимально пластично: чем раньше начать поддержку, тем лучше результат.</p></div>`;
} else if(worstStatus === 'watch'){
html += `<div class="res-doctor"><div class="ic">👀</div><p>Понаблюдайте 34 недели, активно применяя рекомендации выше. Если навыки так и не появляются или вы заметили регресс — обратитесь к педиатру. Лучше перестраховаться, чем упустить время.</p></div>`;
}
// базовые принципы заботливого ухода (всегда)
html += `<div class="res-base"><h4>Базовые принципы заботливого ухода (ВОЗ/ЮНИСЕФ)</h4><ul>` +
BASE_TIPS.map(t=>`<li>${t}</li>`).join('') + `</ul></div>`;
toolResults.innerHTML = html;
}
render();
/* ====== Сбор результатов в Google Таблицу (Apps Script веб-приложение) ====== */
const SHEET_URL = "https://script.google.com/macros/s/AKfycbz0ohb-nons2KY4Y1JUzKB-FNeLpRz5J98v7XM6L5Ic_flUvkbeEyoYcC8jmHeyc220lA/exec";
const collectForm = document.getElementById('collectForm');
const collectOff = document.getElementById('collectOff');
const cEmail = document.getElementById('cEmail');
const cConsent = document.getElementById('cConsent');
const cSubmit = document.getElementById('cSubmit');
const cMsg = document.getElementById('cMsg');
if(SHEET_URL){
collectForm.style.display = 'grid';
collectOff.style.display = 'none';
} else {
collectForm.style.display = 'none';
collectOff.style.display = 'block';
}
function buildSheetPayload(){
const block = DATA[currentAge];
const gotParts=[], missParts=[];
let total=0, done=0;
const out = {age: currentAge};
['phys','cogn','lang','socio'].forEach(key=>{
const items = block[key]||[];
let d=0; const got=[], miss=[];
items.forEach((it,i)=>{
const id=currentAge+'|'+key+'|'+i;
if(checked[id]){d++; got.push(it[0]);} else {miss.push(it[0]);}
});
total+=items.length; done+=d;
const p = items.length?Math.round(d/items.length*100):0;
const st = p>=70?'Хорошо':(p>=40?'Осваивается':'Отстаёт');
out[key+'_done']=d; out[key+'_len']=items.length; out[key+'_st']=st;
if(got.length) gotParts.push(SPHERES[key].name+': '+got.join(', '));
if(miss.length) missParts.push(SPHERES[key].name+': '+miss.join(', '));
});
const pct = total?Math.round(done/total*100):0;
out.pct = pct;
out.overall = pct>=70?'Развитие идёт хорошо':(pct>=40?'Некоторые навыки осваиваются':'Есть сферы, требующие внимания');
out.got = gotParts.join(' | ');
out.miss = missParts.join(' | ');
out.email = cEmail.value.trim();
return out;
}
cSubmit.onclick = async () => {
if(!SHEET_URL){ cMsg.textContent='Приёмник данных не подключён.'; cMsg.className='cmsg err'; return; }
let done=0; Object.keys(checked).forEach(k=>{ if(k.startsWith(currentAge+'|')&&checked[k]) done++; });
if(done===0){ cMsg.textContent='Сначала отметьте хотя бы один навык выше.'; cMsg.className='cmsg err'; return; }
if(!cConsent.checked){ cMsg.textContent='Подтвердите согласие на обработку данных.'; cMsg.className='cmsg err'; return; }
const payload = buildSheetPayload();
cSubmit.disabled = true;
cMsg.textContent='Отправляем…'; cMsg.className='cmsg';
try{
await fetch(SHEET_URL, {
method:'POST',
mode:'no-cors',
headers:{'Content-Type':'text/plain;charset=utf-8'},
body: JSON.stringify(payload)
});
cMsg.textContent='✓ Готово! Результат сохранён в таблицу.'; cMsg.className='cmsg ok';
cConsent.checked=false;
}catch(e){
cMsg.textContent='Нет связи. Проверьте интернет и попробуйте снова.'; cMsg.className='cmsg err';
}
cSubmit.disabled = false;
};
</script>
</body>
</html>

140
prd.md Normal file
View File

@ -0,0 +1,140 @@
# PRD — «Развитие ребёнка»: гид для родителей
> Версия 1.0 · проект `Elena_Tsaai/razvitie-rebenka`
> Живой сайт: https://pages.git.vibe42.kz/Elena_Tsaai/razvitie-rebenka/
> Репозиторий: https://git.vibe42.kz/Elena_Tsaai/razvitie-rebenka
---
## 1. Описание продукта
Одностраничный информационный сайт для родителей, который помогает:
- оценить развитие ребёнка по четырём сферам и возрастам;
- сразу получить персональные рекомендации, если какая-то сфера отстаёт;
- узнать о условиях здорового развития и признаках, при которых нужен специалист;
- обезличенно передать результат оценки владельцу сайта для анализа.
Контент опирается на публикуемые материалы **ВОЗ** и **ЮНИСЕФ**.
## 2. Цели и задачи
| | |
|---|---|
| **Цель продукта** | Дать родителям простой инструмент самопроверки развития ребёнка и поддержать их конкретными советами. |
| **Цель владельца** | Собирать обезличенные данные оценок для анализа: какие сферы/возрасты отстают чаще, какие навыки реже освоены. |
| **Не-цели** | Не диагноз, не замена врачу; не хранение персональных данных детей; не агрегатная статистика в реальном времени на самом сайте (в текущей версии). |
## 3. Целевая аудитория
- **Основной пользователь** — родитель ребёнка 07 лет (не специалист).
- **Владелец/аналитик** — автор сайта, который анализирует собранные данные в Google Таблицах.
## 4. Сценарий использования
1. Родитель открывает сайт, выбирает возраст ребёнка.
2. Отмечает освоенные навыки в чек-листах по 4 сферам.
3. Видит общий прогресс (процент) и прогресс по каждой сфере.
4. Под чек-листами автоматически появляются рекомендации: общий статус + советы по отстающим сферам + блок «когда к специалисту».
5. При желании анонимно отправляет результат (с согласия) — данные попадают в Google Таблицу владельца.
## 5. Функциональные требования
### 5.1. Структура страницы
- Шапка с навигацией (Сферы, Оценка, Уход, Тревоги, Источники).
- Hero: заголовок, подзаголовок, CTA, ключевые цифры.
- Секции: «4 сферы», «Интерактивная оценка», «Заботливый уход», «Красные флаги», «Советы родителям», «Источники», футер.
### 5.2. Сферы развития (4)
- Физическое и моторное (крупные/мелкие движения, рост).
- Когнитивное (познание, игра, причинно-следственные связи).
- Речевое и коммуникативное.
- Социально-эмоциональное.
### 5.3. Интерактивная оценка
- Выбор возраста из 6 периодов: `06 мес`, `612 мес`, `12 года`, `23 года`, `35 лет`, `67 лет`.
- Чек-листы вех развития по каждой сфере (~100 вех суммарно).
- Боковая панель: общее прогресс-кольцо (%), счётчик освоенных вех, прогресс-бары по сферам, индикатор «смотрите рекомендации ниже».
- Отметка навыка кликом; пересчёт в реальном времени.
### 5.4. Автоматические рекомендации
По проценту освоенных вех в сфере определяется статус:
- ≥70% — «Хорошо»
- 4069% — «Осваивается»
- <40% «Отстаёт»
Общий статус = худший по сферам. Выводятся:
- Цветной статус-блок с выводом и пояснением.
- Карточки рекомендаций по сферам со статусом «Отстаёт»/«Осваивается» (конкретные действия родителя).
- Блок «Когда обратиться к специалисту» — заметнее при отставании.
- Базовые принципы заботливого ухода (ВОЗ/ЮНИСЕФ) — всегда.
### 5.5. Заботливый уход
5 условий Nurturing Care Framework (ВОЗ/ЮНИСЕФ/Всемирный банк): здоровье, питание, безопасность и защита, отзывчивая забота, раннее обучение.
### 5.6. Красные флаги
9 сигналов для обращения к специалисту (по срокам ВОЗ): нет улыбки к 2 мес, не держит голову к 34 мес, не сидит к 9 мес, нет лепета/указывания к 12 мес, нет слов к 1618 мес, не ходит к 18 мес, нет фраз к 24 мес, потеря навыков, слабый зрительный контакт.
### 5.7. Советы родителям
6 практических карточек: разговаривать, читать, играть, отвечать на сигналы, кормить по потребности, сон и режим.
### 5.8. Источники
Карточки со ссылками на материалы ВОЗ и ЮНИСЕФ + дисклеймер о неклиническом характере информации.
### 5.9. Сбор данных для анализа
- Форма «Отправить результат» под инструментом оценки.
- Обязательная галочка согласия; поле email родителя — необязательное.
- Отправка напрямую в Google Таблицу через веб-приложение Apps Script.
- Передаются: возраст, общий статус и %, по каждой сфере (освоено/всего/статус), детали освоенных и неосвоенных навыков, дата, email (если указан).
- Имена и контакты детей не собираются.
## 6. Источники данных контента
- ВОЗ — WHO Child Growth Standards (рост/вес/окружность головы).
- ВОЗ — Motor Development Study (6 моторных вех).
- ВОЗ — Improving early childhood development guidelines.
- ЮНИСЕФ — Early Childhood Development.
- ЮНИСЕФ/ВОЗ — Care for Child Development.
- ВОЗ/ЮНИСЕФ/Всемирный банк — Nurturing Care Framework.
## 7. Технические требования и ограничения
- **Только статика:** HTML + CSS + vanilla JS, один файл `index.html`.
- **Без бэкенда, БД, аутентификации, сборщиков.**
- Адаптивная вёрстка (мобильные/десктоп).
- Палитра и типографика — по `design.md` песочницы Vibe42.
- Публикация: push в ветку `pages`, раздаётся через Caddy.
## 8. Сбор и аналитика данных
- **Хранилище:** Google Таблица, приёмник — Apps Script веб-приложение (`doPost`).
- **Передача:** клиентский `fetch` (`mode: no-cors`, `Content-Type: text/plain`, тело — JSON).
- **Схема таблицы:** Дата, Возраст, Общий статус, Общий %, по 4 сферам (освоено/всего/статус), Освоено (детали), Не освоено (детали), Email родителя.
- **Анализ:** сводные таблицы в Google Sheets по возрастам, сферам, статусам; выявление часто отстающих сфер и редко освоенных навыков.
## 9. Приватность и этика
- Данные о развитии ребёнка — чувствительные (здоровье несовершеннолетнего).
- Сбор **анонимный** по умолчанию; email родителя — необязателен.
- Обязательное явное согласие перед отправкой.
- Дисклеймер: инструмент не ставит диагноз; при сомнениях — обратиться к врачу.
## 10. Метрики успеха
- Количество собранных обезличенных оценок.
- Доля оценок со статусом «Отстаёт» (для направления рекомендаций).
- Распределение по возрастам и сферам (где чаще нужна поддержка).
## 11. Возможные следующие шаги (backlog)
- Личная статистика родителя в `localStorage` (история и прогресс во времени).
- Агрегатная live-статистика на сайте через BaaS (например, Supabase) — требует аккаунта.
- Расширение возрастов (подростки), мультиязычность.
- Экспорт сводных отчётов в один клик.
- Интеграция с мессенджерами для связи со специалистом.
## 12. Риски
- Зависимость от внешнего сервиса (Google Apps Script) для сбора данных.
- Ручной характер агрегатного анализа (нет автоматической панели на сайте).
- Возможные искажения: родитель субъективно отмечает навыки; возрастные диапазоны широкие.
- Этические риски при сборе данных о детях — смягчаются анонимностью и согласием.