diff --git a/medcenter/.claude/launch.json b/medcenter/.claude/launch.json
new file mode 100644
index 0000000..3f11edc
--- /dev/null
+++ b/medcenter/.claude/launch.json
@@ -0,0 +1,11 @@
+{
+ "version": "0.0.1",
+ "configurations": [
+ {
+ "name": "medcenter-dev",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": ["run", "dev:client"],
+ "port": 5173
+ }
+ ]
+}
diff --git a/medcenter/.env.example b/medcenter/.env.example
new file mode 100644
index 0000000..98d2b2d
--- /dev/null
+++ b/medcenter/.env.example
@@ -0,0 +1,34 @@
+# ---------------------------------------------------------------------------
+# Public (baked into the client bundle at build time — never put secrets here)
+# ---------------------------------------------------------------------------
+VITE_SITE_URL=https://exodevices.ru/medical-centers/with-physiotherapy
+
+# Sub-path the site is served from, if any. Leave as "/" when it sits at the
+# domain root; set to "/medical-centers/with-physiotherapy/" when it is mounted
+# under that path.
+VITE_BASE_PATH=/
+
+# ---------------------------------------------------------------------------
+# Server
+# ---------------------------------------------------------------------------
+PORT=3000
+
+# ---------------------------------------------------------------------------
+# amoCRM — server-side only, never exposed to the browser
+# ---------------------------------------------------------------------------
+# Your account subdomain: for https://exotherapy.amocrm.ru put "exotherapy"
+AMO_SUBDOMAIN=
+
+# Long-lived access token.
+# amoCRM → Настройки → Интеграции → Создать интеграцию → Внешняя интеграция →
+# open it → tab "Ключи и скопы" → «Генерировать токен» (долгосрочный, ~1 год).
+AMO_LONG_LIVED_TOKEN=
+
+# Pipeline (воронка) the leads land in. The lead is placed in its first stage.
+AMO_PIPELINE_ID=10980758
+
+# Optional: numeric id of the amoCRM user leads are assigned to.
+AMO_RESPONSIBLE_USER_ID=
+
+# Optional: comma-separated tags added to every lead.
+AMO_LEAD_TAGS=medcenter-landing
diff --git a/medcenter/.gitignore b/medcenter/.gitignore
new file mode 100644
index 0000000..23fc33a
--- /dev/null
+++ b/medcenter/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+dist
+.env
+.env.local
+*.local
+.DS_Store
diff --git a/medcenter/README.md b/medcenter/README.md
new file mode 100644
index 0000000..efeb33e
--- /dev/null
+++ b/medcenter/README.md
@@ -0,0 +1,149 @@
+# Усиление действующего кабинета физиотерапии — лендинг для медицинских центров
+
+React-приложение лендинга MedCsFiz (медицинский центр, у которого физиотерапия
+уже есть). Каждая заявка создаёт сделку в amoCRM (воронка `10980758`) и контакт,
+если его ещё нет.
+
+Стек: **Vite + React 19 + TypeScript + Tailwind CSS v4**, API — **Express 5**.
+
+---
+
+## Быстрый старт
+
+```bash
+npm install
+cp .env.example .env # заполнить AMO_SUBDOMAIN и AMO_LONG_LIVED_TOKEN
+npm run dev
+```
+
+`npm run dev` поднимает Vite на `http://localhost:5173` и API на `:3000`;
+запросы `/api/*` проксируются с фронтенда на API.
+
+## Продакшен
+
+```bash
+npm run build # сборка клиента в dist/client
+npm start # Express отдаёт dist/client и обрабатывает /api/*
+```
+
+Один процесс Node на любом VPS. Порт — `PORT` (по умолчанию 3000).
+
+---
+
+## amoCRM
+
+### 1. Получить долгосрочный токен
+
+1. amoCRM → **Настройки → Интеграции → Создать интеграцию → Внешняя интеграция**.
+2. Название любое (например «Сайт medcenter»), redirect URI — любой рабочий
+ адрес сайта: для долгосрочного токена он не используется.
+3. Права доступа: достаточно **Сделки, Контакты** (чтение и запись).
+4. Сохранить, открыть интеграцию → вкладка **«Ключи и скопы»** →
+ **«Генерировать токен»** (долгосрочный, действует ~1 год).
+5. Скопировать токен в `.env` в `AMO_LONG_LIVED_TOKEN`, поддомен — в
+ `AMO_SUBDOMAIN` (для `https://exotherapy.amocrm.ru` это `exotherapy`).
+
+Токен читается только на сервере и никогда не попадает в браузерный бандл.
+Пометьте в календаре дату истечения — токен нужно перевыпустить через год.
+
+### 2. Проверить подключение
+
+```bash
+npm run amo:check
+```
+
+Скрипт выведет название аккаунта, первый этап воронки `10980758`, в который
+попадут сделки, и то, в какие поля вашего аккаунта легли данные формы.
+
+### 3. Что происходит при отправке формы
+
+1. Поиск контакта по телефону (во всех написаниях: `+7…`, `8…`, только цифры)
+ и по email. Если контакт найден — используется он, недостающий телефон или
+ email дописывается в карточку.
+2. Если контакта нет — создаётся новый с именем, телефоном и email.
+3. Создаётся сделка в воронке `AMO_PIPELINE_ID`, в её **первом этапе**,
+ с тегами `AMO_LEAD_TAGS` + тег `заявка с сайта`.
+4. Данные, для которых в аккаунте есть подходящее поле (компания, состояние
+ кабинета, профиль, `utm_*` и т.д.), пишутся в поля; всё остальное — в
+ примечание к сделке. Ничего настраивать в amoCRM заранее не нужно.
+
+Если amoCRM недоступна, заявка **не теряется**: она пишется в лог сервера
+(`[lead] payload was: …`) и сохраняется в `localStorage` браузера, а посетитель
+видит телефон для связи.
+
+### Переменные окружения
+
+| Переменная | Обязательна | Описание |
+|---|---|---|
+| `AMO_SUBDOMAIN` | да | Поддомен аккаунта, например `exotherapy` |
+| `AMO_LONG_LIVED_TOKEN` | да | Долгосрочный токен интеграции |
+| `AMO_PIPELINE_ID` | нет | Воронка для сделок (по умолчанию `10980758`) |
+| `AMO_RESPONSIBLE_USER_ID` | нет | Ответственный за сделку пользователь |
+| `AMO_LEAD_TAGS` | нет | Теги через запятую для всех сделок |
+| `PORT` | нет | Порт API/продакшен-сервера (`3000`) |
+| `VITE_SITE_URL` | нет | Канонический адрес, подставляется в `canonical` и `og:` |
+| `VITE_BASE_PATH` | нет | Подпуть размещения, например `/medical-centers/with-physiotherapy/` (по умолчанию `/`) |
+
+---
+
+## Структура
+
+```
+index.html точка входа Vite (meta, Open Graph, JSON-LD)
+src/
+ components/ секции лендинга и UI-примитивы
+ data/content.ts весь текстовый контент страницы
+ hooks/useReveal.ts анимация появления секций при скролле
+ lib/ отправка заявки, маска телефона
+ assets/images/ 12 изображений, извлечённых из исходного HTML
+ index.css дизайн-токены Tailwind v4 (@theme) и базовые стили
+shared/lead.ts схема заявки (zod), общая для клиента и сервера
+server/src/ Express API + клиент amoCRM
+scripts/amo-check.ts диагностика подключения к amoCRM
+legacy/index.html исходный однофайловый лендинг (визуальный эталон)
+```
+
+### Дизайн-система
+
+Цвета, радиусы, тени, брейкпоинты и вертикальный ритм заданы токенами в
+`@theme` внутри `src/index.css`. Палитра Tailwind по умолчанию отключена
+(`--color-*: initial`), поэтому в разметке доступны только цвета EXO.
+Брейкпоинты соответствуют исходной вёрстке: `sm` 600, `md` 760, `lg` 980, плюс
+`max-width`-варианты `stack` (1050), `narrow` (760), `compact` (560),
+`phone` (520), `tiny` (430). Они объявлены от широкого к узкому — Tailwind
+выводит варианты в порядке объявления, и более узкий должен идти позже, чтобы
+выигрывать.
+
+Горизонтальные ряды карточек (рынок, обещания, оборудование, программы,
+форматы, план) используют класс `.scroll-cards`: на телефоне это лента со
+snap-скроллом, а на нужной ширине секция сама возвращает её в обычную сетку
+через `sm:grid-still` / `md:grid-still`.
+
+### Шрифты
+
+Inter подключён локально пакетом `@fontsource-variable/inter` — внешних запросов
+(Google Fonts и т.п.) страница не делает. Это вариативный шрифт с диапазоном
+100–900, поэтому нестандартные веса из макета (720, 760, 790, 850) отрисовываются
+по-настоящему, а не округляются до `bold`.
+
+Символы `≈ − ×` не входят в подсеты Inter у Fontsource, поэтому для них всегда
+используется системный фолбэк. Это заметно только при очень крупном кегле.
+
+`Manrope` и `Segoe UI` остались в стеке `--font-sans` как фолбэк, но отдельно не
+загружаются.
+
+### Экономика кабинета
+
+Все цифры блоков «Деньги уходят мимо Вас» и «Сценарии выручки» — статические
+данные из `src/data/content.ts`, как в исходном лендинге. Калькулятора на
+странице нет: расчёт делается на аудите.
+
+---
+
+## Известные особенности
+
+* `og:image` отдаётся по абсолютному адресу `VITE_SITE_URL` + `/og-image.webp`;
+ при смене домена обновите `VITE_SITE_URL` перед сборкой.
+* Две фотографии аппаратов (ЭкзоЛазер В и ЭкзоИмпульс) в исходном файле были
+ PNG на 1,5 МБ и 750 КБ — здесь они пережаты в webp с сохранением
+ прозрачности, как и остальные снимки оборудования.
diff --git a/medcenter/index.html b/medcenter/index.html
new file mode 100644
index 0000000..f7bf089
--- /dev/null
+++ b/medcenter/index.html
@@ -0,0 +1,47 @@
+
+
+
Решение для медицинского центра с действующей физиотерапией
+
Усилим кабинет физиотерапии — без замены действующего оборудования
+
Проводим аудит оборудования, документы и загрузку, сохраняем полезные активы, убираем дублирование, добавляем только недостающие технологии и объединяем старое и новое в единые клинические маршруты.
Вы уже вложились в кабинет и оборудование, но выручка не растёт. Проблема не в трафике — проблема в том, как используется текущая база.
+
+
+
+
+
+ Где вы теряете деньги уже сегодня
+
+
+
+
+1 000
+активных пациентов в базе за год
+
+
+
Не предложили курс
−35%
+
Нет повторных визитов
−30%
+
Нет регулярного сопровождения
−25%
+
Нет комплексного подхода
−20%
+
+
+
+≈200
+пациентов доходят до выручки за год
+
+
+
+
+Сколько денег уходит мимо вас каждый год
+≈ 20 000 000 ₽
+потенциальной выручки теряется из-за неиспользованного потенциала текущей базы
+
+
+
Не предложили курс (−35%)≈ 9 450 000 ₽
+
Нет повторных визитов (−30%)≈ 6 750 000 ₽
+
Нет регулярного сопровождения (−25%)≈ 2 970 000 ₽
+
Нет комплексного подхода (−20%)≈ 810 000 ₽
+
+
+
+
+
+
+ Как мы превращаем потери в дополнительную выручку
+
+
+
Системная работаСтандартизация процессов, назначений и скриптов.
+
Курсовой подходПлан лечения оформляется как понятный курс.
+
Повторные визитыКонтроль результата и плановое сопровождение пациента.
+
Комплексные программыКомбинация действующих методик и оборудования ЭКЗО.
+
+
Результат: выручка растёт за счёт текущей базы
+
+
1 000активных пациентов в базе за год
+
×
+
27 000 ₽средний чек курса
+
×
+
4цикла в год
+
=
+
108 000 000 ₽дополнительной выручки в год без вложений в маркетинг
+
+
+
+108 000 000 ₽дополнительная выручка в год
+
60–70%маржинальность услуг
+
0 ₽дополнительных расходов на маркетинг
+
3–6 мес.срок окупаемости внедрения
+
+
+
+
+
+
+
Мы не приводим новых пациентов.
Мы увеличиваем выручку с тех, кто уже у вас есть.
+
+
+
+
Не теряйте деньги. Превратите свою базу в источник стабильного роста.
+
+
+
Сценарная модель. Фактический потенциал рассчитывается после аудита базы, расписания, действующего оборудования, тарифов и структуры курсов.
+
+
+
+
Сценарии выручки
+
Даже умеренная загрузка кабинета даёт понятную выручку
+
Модель считается просто: количество оплаченных курсов × средний чек курса. Дальше на аудите добавляем расходы и срок окупаемости.
+
Формула расчёта
оплаченные курсы × средний чек ≈ 27 000 ₽
без учёта расходов
+
+
30курсов в месяц
0,81 млн ₽осторожный сценарий
+
60курсов в месяц
1,62 млн ₽рабочая загрузка
+
100курсов в месяц
2,70 млн ₽сильная загрузка
+
+
Что превращает расчёт в окупаемость
+
Загрузка кабинета
Доля курсов
Повторные визиты
Средний чек
+
На финальном расчёте считаем CAPEX, ФОТ, площадь, аренду, расходники, налоги и маркетинг. Здесь показана рамка выручки, чтобы быстро понять порядок потенциала.
Мы начинаем не с аппаратов ЭКЗО, а с аудита уже сделанных инвестиций клиники: технических возможностей, документов, клинической роли, назначений, загрузки и экономики каждого аппарата.
+
+
+
+
+
Загрузить действующее оборудование
+
Вернуть полезным аппаратам точную роль, назначающих врачей, расписание и понятный курс.
+
+
+
+
Закрыть клинические пробелы
+
Добавить только те EXO-модули, которых не хватает текущим врачебным маршрутам.
+
+
+
+
Увеличить пропускную способность
+
Развести активные и параллельные процедуры, сократить простои и собрать пакетные программы.
+
+
+
+
Управлять результатом
+
Измерять назначения, завершение курса, загрузку, динамику, повторные программы и экономику.
+
+
+
+
+
Инвестиция направляется не на замену всего текущего оборудования, а на закрытие конкретных клинических и операционных разрывов.
+
+
Профили, для которых особенно актуальна модернизация:
+
+Травматология и ортопедияНеврологияПослеоперационная реабилитацияСпортивная медицинаРевматологияФлебология / лимфологияГинекология / УрологияЭстетическая медицина
+
+
+
+
+
+
+
+
+
+
Технологический конструктор
Существующее оборудование + недостающие EXO-модули
+
Для действующего кабинета не нужно покупать всё сразу. По итогам аудита выбираются платформы, которые закрывают конкретные клинические и операционные пробелы — без повторения уже имеющихся факторов.
+
+
+
+
Системное усиление
ЭкзоТерапия
ОДА • неврология • дыхательная система • сосуды • органы малого таза • ЖКТ
электромагнитная стимуляция • нервно-мышечная система • устранение спазмов и зажимов • активация регенерации • противовоспалительный эффект • микроциркуляция и лимфодренаж • снятие глубоких мышечных болей • восстановление двигательной активности • реабилитация при неврологических патологиях
+
Фокусированная ударно-волновая терапия
+
+
+
+
На мобильном — листайте карточки в сторону
+
+
+Сначала выбирается клиническая задача и проверяется роль действующих методов. Затем подбирается недостающая технология. Аппараты применяются как инструмент врача; показания, противопоказания, квалификация персонала и формулировки сверяются с актуальной регистрационной документацией и лицензией клиники.
+
+
+
+
+
+
+
Комбинированные маршруты
+
Старые и новые аппараты перестают быть отдельными услугами
+
Действующие процедуры, ЛФК, массаж и EXO-технологии объединяются в курс под состояние пациента, этап реабилитации и утверждённую клиническую модель.
+
+
+
+
01
Нейрореабилитация
Наше оборудование помогает пациентам восстановить двигательные функции, в т.ч. после инсульта, снизить проявления спастичности и парезов, улучшить баланс и координацию.
02
Травматология и ортопедия
Устройства обеспечивают эффективную реабилитацию после переломов и эндопротезирования, способствуют снятию отёка и боли, повышают подвижность суставов и предупреждают развитие контрактур.
03
Послеоперационное восстановление
Оборудование позволяет активизировать пациентов в ранние сроки, стимулирует регенерацию тканей и снижает риск послеоперационных осложнений.
04
Хронические боли и дегенеративные заболевания
При остеохондрозе и артрозах оборудование помогает снизить болевой синдром и улучшить трофику и подвижность поражённых участков.
05
Детская реабилитация
Специальные методики способствуют развитию моторных навыков у детей с ДЦП, укрепляют мышечный корсет и помогают освоить вертикальное положение.
06
Спортивная медицина
Оборудование ускоряет восстановление спортсменов после травм и перегрузок, помогает грамотно вернуться к тренировкам и соревнованиям.
07
Паллиативная поддержка
Устройства облегчают хроническую боль и помогают сохранить функциональную активность на максимально возможном уровне.
+
На мобильном — листайте программы
+
+
+
+
+
+
+
+
+
+
Три модели усиления
Можно начать точечно — без длительного закрытия кабинета
+
Формат определяется после аудита оборудования, расписания и клинических пробелов. Расширение происходит только после того, как пилот подтверждает назначения, загрузку, результат и экономику.
+
+
от 12 м²
Один кабинет
Стартовый формат под отдельный сценарий и ограниченную конфигурацию.
от 35 м²
Два кабинета
Базовая инфраструктура с разделением активных и параллельных процедур.
от 45 м²
Три кабинета
Расширенный формат для нескольких маршрутов и большей пропускной способности.
+
Финальная конфигурация определяется по техническому состоянию аппаратов, документации, площади, лицензии, штату, потоку пациентов и текущей загрузке.
+
+
Пошаговый план модернизации кабинета за 8 недель
1–2 неделя.Сбор данных и комплексный аудит кабинетаМы проводим глубокий технический аудит текущего оборудования. Анализируем действующее направление по нозологиям, сроки лечения и методики.
Инвентаризация и аудит оборудования: Проверка технического состояния, износа и реальной загрузки каждого действующего аппарата клиники.
Анализ расписания и логистики: Поиск «узких мест» в сетке записи, из-за которых простаивают кабинеты и формируются простои у врачей.
Экспертиза документов: Проверка действующих медицинских лицензий, соответствия стандартам оснащения Минздрава и текущих карт назначений.
Анализ штата и мотивации: Оценка квалификации врачей и медсестёр, анализ их загрузки и текущей схемы оплаты труда.
Оцифровка экономики и потока: Расчёт стоимости одного визита пациента, маржинальности отдельных процедур и объёма упущенной прибыли клиники.
3–4 неделя.Разработка карты пробелов и проектирование EXO-маршрутовНа основе аудита мы создаём индивидуальное инженерное и медицинское решение под специфику вашей клиники.
План по увеличению нагрузки на действующие аппараты
План по увеличению пропускной способности одного кабинета
Формирование индивидуальных комплексных методик
План перезонирования
5–6 неделя.Бесшовное дооснащение и комплексное обучение командыМы интегрируем оборудование и готовим команду к новой модели работы без остановки текущего приёма пациентов. Все технические и образовательные процессы подстраиваются под график вашей клиники.
Бесшовный монтаж и калибровка: Установка модулей производится в удобное для вас время, включая выходные или вечерние часы. Клиника продолжает принимать пациентов в штатном режиме — вы не теряете ни одного дня выручки.
Гибкий формат обучения персонала: Мы подбираем комфортный график занятий без отрыва сотрудников от работы. Дополнительно доступна опция обучения на базе нашей действующей клиники.
Внедрение технологических карт: Интеграция готовых протоколов лечения в МИС клиники для быстрой работы врачей.
Обучение врачей: Глубокий курс по сочетанным методикам EXO-терапии, биомеханике, оценке динамики пациента и показаниям для курсового лечения.
Инструктаж медицинских сестёр: Практическая отработка навыков проведения параллельных процедур и контроля безопасности.
Подготовка администраторов: Обучение сервисного персонала работе со скриптами, алгоритмам удержания пациентов и правилам презентации комплексных пакетов.
7–8 неделя.Мягкий перезапуск, запуск пакетов и аналитикаЗапуск обновлённого кабинета в работу, перевод текущих пациентов на новые маршруты и фиксация первых финансовых результатов.
Работа с действующими пациентами: Мягкий перевод пациентов с разовых процедур на новые комбинированные EXO-программы.
Старт продаж новых пакетов услуг: Внедрение высокомаржинальных курсовых продуктов вместо неэффективной поштучной продажи визитов.
Внедрение контроля «до / после»: Запуск системы объективной оценки результатов лечения: снимки, тесты и шкалы боли.
Аналитика первой прибыли: Оценка динамики загрузки кабинета, роста среднего чека и удовлетворённости пациентов за первые 14 дней работы.
Дорожная карта по увеличению целевой аудитории: План расширения спектра оказываемых услуг и дальнейшего развития кабинета.
+
+
+
+
+
+
+
+
Почему Экзо Групп
+
Аудит, интеграция, производство и сопровождение — в одном контуре
+
Обычная поставка начинается с выбора аппарата. Экзо Групп начинает с действующего кабинета и отвечает за переход от разрозненного оборудования к работающему направлению.
+
+
+
+
+
Российское производство и сервисПроизводственная и сервисная инфраструктура в Тольятти, технопарк «Жигулёвская долина».
+
+
+
+
Аудит вместо типовой закупкиОцениваем парк, документы, загрузку, назначения и клинические пробелы до формирования комплектации.
+
Собственная клиническая практикаОборудование, маршруты и организация работы проверяются внутри сети Экзо Клиник.
+
Обучение по ролямВрачи назначают, медсёстры выполняют, главный врач контролирует, администратор доводит пациента до курса.
+
+
+
100+точек установки
+
60+медицинских учреждений
+
60 днейдо модели «до / после»
+
+
Количественные показатели — по корпоративным материалам Экзо Групп. Срок пилота ориентировочный и зависит от помещения, лицензии, поставки и обучения.
+
+
+
+
+
+
+
+
Следующий шаг
+
Усилим действующий кабинет — без лишнего дублирования
+
Оставьте контакты — специалист уточнит состав оборудования, услуги, загрузку, врачебные направления и задачи центра, после чего подготовит предварительную дорожную карту модернизации.
+
+
аудит действующего оборудования и решение по каждому аппарату;
+
EXO-конфигурация только под выявленные пробелы;
+
план пилота на 60 дней и KPI «до / после».
+
+
+
+
+
+
+
+
+
+ИННОВАЦИОННАЯ ЭКОСИСТЕМА
+Экзо Групп — резидент ведущих технологических площадок
+
+
+
+ На мобильном — листайте карточки в сторону
+
+
+
svg]:size-[20px] [&>svg]:shrink-0 [&>svg]:text-teal-bright',
+ note.revealClass,
+ )}
+ >
+
+
+ Сначала выбирается клиническая задача и проверяется роль действующих методов. Затем подбирается недостающая
+ технология. Аппараты применяются как инструмент врача; показания, противопоказания, квалификация персонала и
+ формулировки сверяются с актуальной регистрационной документацией и лицензией клиники.
+
+
+ )
+}
diff --git a/medcenter/src/components/Hero.tsx b/medcenter/src/components/Hero.tsx
new file mode 100644
index 0000000..f3a9e4d
--- /dev/null
+++ b/medcenter/src/components/Hero.tsx
@@ -0,0 +1,75 @@
+import heroBg from '../assets/images/hero-bg.webp'
+import { heroFacts } from '../data/content'
+import { useReveal } from '../hooks/useReveal'
+import { cx } from '../lib/cx'
+import { ButtonLink } from './Button'
+import { ArrowRightIcon } from './Icons'
+import { Container, Eyebrow } from './Layout'
+
+export function Hero() {
+ const { ref, revealClass } = useReveal()
+
+ return (
+
+
+
+
+
+
+
+ Решение для медицинского центра с действующей физиотерапией
+
+
Усилим кабинет физиотерапии — без замены действующего оборудования
+
+
+ Проводим аудит оборудования, документы и загрузку, сохраняем полезные активы, убираем дублирование,
+ добавляем только недостающие технологии и объединяем старое и новое в единые клинические маршруты.
+
+
+
+
+ Получить предложение
+
+
+
+ Посмотреть модели усиления
+
+
+
+
+ {heroFacts.map((fact) => (
+
+
+ {fact.value}
+
+ {fact.label}
+
+ ))}
+
+
+
+
+ Рост загрузки уже сделанных инвестиций — вместо тотальной замены оборудования
+
+
+
+
+ )
+}
diff --git a/medcenter/src/components/Icons.tsx b/medcenter/src/components/Icons.tsx
new file mode 100644
index 0000000..e942cd9
--- /dev/null
+++ b/medcenter/src/components/Icons.tsx
@@ -0,0 +1,180 @@
+import type { ReactNode } from 'react'
+
+/** Every icon on the page is a 24×24 outline drawn in `currentColor`. */
+function Icon({ children }: { children: ReactNode }) {
+ return (
+
+ )
+}
+
+export function ArrowRightIcon() {
+ return (
+
+
+
+ )
+}
+
+export function CheckIcon() {
+ return (
+
+
+
+ )
+}
+
+export function PhoneIcon() {
+ return (
+
+
+
+ )
+}
+
+/* -------------------------------------------------------------------------- */
+/* Экономика действующего кабинета */
+/* -------------------------------------------------------------------------- */
+
+/** Panel title: «Где вы теряете деньги уже сегодня». */
+export function WarningIcon() {
+ return (
+
+
+
+
+
+ )
+}
+
+/** Panel title: «Как мы превращаем потери в дополнительную выручку». */
+export function TrendUpIcon() {
+ return (
+
+
+
+
+ )
+}
+
+/** Left anchor of the leak diagram: the patient base. */
+export function PatientsIcon() {
+ return (
+
+
+
+
+
+ )
+}
+
+/** Right anchor of the leak diagram: what is left of the revenue. */
+export function RevenueBarsIcon() {
+ return (
+
+
+
+ )
+}
+
+/** Closing statement: turn the base into steady growth. */
+export function GrowthBarsIcon() {
+ return (
+
+
+
+ )
+}
+
+/** Icons of the four «как превращаем потери» tiles, keyed by `leakSolutions[].icon`. */
+export const solutionIcons = {
+ gear: (
+
+
+
+
+ ),
+ clipboard: (
+
+
+
+
+
+ ),
+ repeat: (
+
+
+
+
+ ),
+ layers: (
+
+
+
+
+ ),
+}
+
+/* -------------------------------------------------------------------------- */
+/* Модернизация и «почему Экзо» */
+/* -------------------------------------------------------------------------- */
+
+/** Icons of the four promise cards, keyed by `promises[].icon`. */
+export const promiseIcons = {
+ load: (
+
+
+
+ ),
+ gap: (
+
+
+
+ ),
+ throughput: (
+
+
+
+ ),
+ result: (
+
+
+
+ ),
+}
+
+/** Icons of the «почему Экзо Групп» list, keyed by `whyItems[].icon`. */
+export const whyIcons = {
+ audit: (
+
+
+
+ ),
+ clinic: (
+
+
+
+ ),
+ roles: (
+
+
+
+ ),
+}
diff --git a/medcenter/src/components/LaunchSection.tsx b/medcenter/src/components/LaunchSection.tsx
new file mode 100644
index 0000000..d30a365
--- /dev/null
+++ b/medcenter/src/components/LaunchSection.tsx
@@ -0,0 +1,76 @@
+import { formats, timeline } from '../data/content'
+import { useReveal } from '../hooks/useReveal'
+import { cx } from '../lib/cx'
+import { Container, Section, SectionHead, SmallNote } from './Layout'
+
+export function LaunchSection() {
+ const grid = useReveal()
+ const steps = useReveal()
+
+ return (
+
+
+
+
+
+
+ Вы уже вложились в кабинет и оборудование, но выручка не растёт. Проблема не в трафике — проблема в том, как
+ используется текущая база.
+
+
+
+
+ {/* ------------------------------------------------------------- */}
+ {/* Где вы теряете деньги */}
+ {/* ------------------------------------------------------------- */}
+
+
+
+ Где вы теряете деньги уже сегодня
+
+
+
+
+
+
+
+
+ {/* The pipe the leaks drip out of. Hidden once the stages wrap. */}
+
+
+ {leakStages.map((stage) => (
+
+
+ Сколько денег уходит мимо вас каждый год
+
+
+ ≈ 20 000 000 ₽
+
+
+ потенциальной выручки теряется из-за неиспользованного потенциала текущей базы
+
+
+
+
+ {leakBreakdown.map((row) => (
+
+ {row.label}
+ {row.value}
+
+ ))}
+
+
+
+
+ {/* ------------------------------------------------------------- */}
+ {/* Как превращаем потери в выручку */}
+ {/* ------------------------------------------------------------- */}
+
+
+
+ Как мы превращаем потери в дополнительную выручку
+
+
+
+ {leakSolutions.map((solution) => (
+
+
+ {solutionIcons[solution.icon]}
+
+
+ {solution.title}
+ {solution.text}
+
+
+ ))}
+
+
+
+ Результат: выручка растёт за счёт текущей базы
+
+
+
+ )
+}
diff --git a/medcenter/src/components/RequestSection.tsx b/medcenter/src/components/RequestSection.tsx
new file mode 100644
index 0000000..95fe89b
--- /dev/null
+++ b/medcenter/src/components/RequestSection.tsx
@@ -0,0 +1,39 @@
+import { ctaChecks } from '../data/content'
+import { useReveal } from '../hooks/useReveal'
+import { cx } from '../lib/cx'
+import { CheckIcon } from './Icons'
+import { Container, Eyebrow, SectionLead } from './Layout'
+import { LeadForm } from './LeadForm'
+
+export function RequestSection() {
+ const copy = useReveal()
+
+ return (
+
+
+
+ Следующий шаг
+
Усилим действующий кабинет — без лишнего дублирования
+
+ Оставьте контакты — специалист уточнит состав оборудования, услуги, загрузку, врачебные направления и задачи
+ центра, после чего подготовит предварительную дорожную карту модернизации.
+
+
+
+ {ctaChecks.map((check) => (
+
+
+ {check}
+
+ ))}
+
+
+
+
+
+
+ )
+}
diff --git a/medcenter/src/components/ResidencySection.tsx b/medcenter/src/components/ResidencySection.tsx
new file mode 100644
index 0000000..c8dbc6d
--- /dev/null
+++ b/medcenter/src/components/ResidencySection.tsx
@@ -0,0 +1,53 @@
+import skolkovo from '../assets/images/resident-skolkovo.svg'
+import zhiguli from '../assets/images/resident-zhiguli.svg'
+import { residencies } from '../data/content'
+
+const logos = [zhiguli, skolkovo]
+
+export function ResidencySection() {
+ return (
+
+
+
+
+
+
+ ИННОВАЦИОННАЯ ЭКОСИСТЕМА
+
+
+ Экзо Групп — резидент ведущих технологических площадок
+
+
+
+ )
+}
diff --git a/medcenter/src/components/ScenariosSection.tsx b/medcenter/src/components/ScenariosSection.tsx
new file mode 100644
index 0000000..e0d8ae0
--- /dev/null
+++ b/medcenter/src/components/ScenariosSection.tsx
@@ -0,0 +1,86 @@
+import { revenueDrivers, revenueScenarios } from '../data/content'
+import { useReveal } from '../hooks/useReveal'
+import { cx } from '../lib/cx'
+import { ButtonLink } from './Button'
+import { ArrowRightIcon } from './Icons'
+import { Container, Eyebrow, Section } from './Layout'
+
+export function ScenariosSection() {
+ const cta = useReveal()
+
+ return (
+
+
+
+ Сценарии выручки
+
+
+
+ Даже умеренная загрузка кабинета даёт понятную выручку
+
+
+ Модель считается просто: количество оплаченных курсов × средний чек курса. Дальше на аудите добавляем расходы и
+ срок окупаемости.
+
+
+
+ Формула расчёта
+
оплаченные курсы × средний чек ≈ 27 000 ₽
+ без учёта расходов
+
+
+
+ {revenueScenarios.map((scenario) => (
+
+
+
+ {scenario.courses}
+
+ курсов в месяц
+
+ {scenario.revenue}
+ {scenario.note}
+
+ ))}
+
+
+
Что превращает расчёт в окупаемость
+
+ {revenueDrivers.map((driver) => (
+
+ {driver}
+
+ ))}
+
+
+
+ На финальном расчёте считаем CAPEX, ФОТ, площадь, аренду, расходники, налоги и маркетинг. Здесь показана рамка
+ выручки, чтобы быстро понять порядок потенциала.
+
+
+
+
+ Как получить выручку?
+
+
+
+ Перейдите к форме — подготовим расчёт потенциала для вашего кабинета.
+
+
+
+
+ )
+}
diff --git a/medcenter/src/components/SiteFooter.tsx b/medcenter/src/components/SiteFooter.tsx
new file mode 100644
index 0000000..4056f1e
--- /dev/null
+++ b/medcenter/src/components/SiteFooter.tsx
@@ -0,0 +1,32 @@
+import logo from '../assets/images/exo-logo.png'
+import { Container } from './Layout'
+
+export function SiteFooter() {
+ return (
+
+ )
+}
diff --git a/medcenter/src/components/SiteHeader.tsx b/medcenter/src/components/SiteHeader.tsx
new file mode 100644
index 0000000..4433b59
--- /dev/null
+++ b/medcenter/src/components/SiteHeader.tsx
@@ -0,0 +1,49 @@
+import logo from '../assets/images/exo-logo.png'
+import { contacts, navLinks } from '../data/content'
+import { ButtonLink, buttonClass, headerSize } from './Button'
+import { PhoneIcon } from './Icons'
+import { Container } from './Layout'
+
+/**
+ * The original ended up with the blurred background painted unconditionally —
+ * the last stylesheet override drops the scroll-dependent variant — so there is
+ * no scroll state to track here.
+ */
+export function SiteHeader() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/medcenter/src/components/WhyExoSection.tsx b/medcenter/src/components/WhyExoSection.tsx
new file mode 100644
index 0000000..17a053a
--- /dev/null
+++ b/medcenter/src/components/WhyExoSection.tsx
@@ -0,0 +1,84 @@
+import productionSite from '../assets/images/production-site.webp'
+import { companyStats, whyItems } from '../data/content'
+import { useReveal } from '../hooks/useReveal'
+import { cx } from '../lib/cx'
+import { whyIcons } from './Icons'
+import { Container, Section, SectionHead, SmallNote } from './Layout'
+
+export function WhyExoSection() {
+ const photo = useReveal()
+ const list = useReveal()
+ const stats = useReveal()
+
+ return (
+
+
+
+
+
+
+
+
+ Российское производство и сервис
+
+ Производственная и сервисная инфраструктура в Тольятти, технопарк «Жигулёвская долина».
+
+
+
+
+
+
+ {whyItems.map((item) => (
+
+
+ {whyIcons[item.icon]}
+
+
+ {item.title}
+ {item.text}
+
+
+ ))}
+
+
+
+ {companyStats.map((stat) => (
+
+ {stat.value}
+ {stat.label}
+
+ ))}
+
+
+
+ Количественные показатели — по корпоративным материалам Экзо Групп. Срок пилота ориентировочный и зависит
+ от помещения, лицензии, поставки и обучения.
+
+
+
+
+
+ )
+}
diff --git a/medcenter/src/data/content.ts b/medcenter/src/data/content.ts
new file mode 100644
index 0000000..07e7f08
--- /dev/null
+++ b/medcenter/src/data/content.ts
@@ -0,0 +1,500 @@
+import deviceHydrogen from '../assets/images/device-hydrogen.webp'
+import deviceImpulse from '../assets/images/device-impulse.webp'
+import deviceLaser from '../assets/images/device-laser.webp'
+import deviceMagnet from '../assets/images/device-magnet.webp'
+import devicePress from '../assets/images/device-press.webp'
+import deviceTecar from '../assets/images/device-tecar.webp'
+import deviceTherapy from '../assets/images/device-therapy.webp'
+
+export const contacts = {
+ phone: '+7 939 717-80-80',
+ phoneHref: 'tel:+79397178080',
+}
+
+export const navLinks = [
+ { href: '#market', label: 'Почему усиливать' },
+ { href: '#project', label: 'Как модернизируем' },
+ { href: '#technology', label: 'Конструктор' },
+ { href: '#launch', label: 'Пилот' },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Первый экран */
+/* -------------------------------------------------------------------------- */
+
+export const heroFacts = [
+ { value: '6 решений', label: 'по каждому действующему аппарату' },
+ { value: '60 дней', label: 'до усиленной модели «до / после»' },
+ {
+ value: '35% к чистой прибыли',
+ label: 'превращаем кабинет физиотерапии в главный источник дохода клиники',
+ },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Рыночный контекст */
+/* -------------------------------------------------------------------------- */
+
+export const marketStats = [
+ {
+ value: '2,41',
+ label: 'млрд людей в мире живут с состояниями, при которых может быть полезна реабилитация',
+ source: 'WHO / IHME',
+ },
+ { value: '+63%', label: 'рост глобальной потребности в реабилитации с 1990 года', source: 'WHO / IHME' },
+ {
+ value: '1,14 → 1,79',
+ label: 'млн пациентов получили медицинскую реабилитацию по ОМС в России, 2022–2025',
+ source: 'Минздрав России',
+ },
+ {
+ value: '+26,5%',
+ label: 'целевой рост числа получателей медицинской реабилитации к 2030 году',
+ source: 'Федеральный проект',
+ },
+]
+
+/** Пациенты медицинской реабилитации по ОМС, млн человек. */
+export const trendBars = [
+ { year: '2022', value: '1,14', height: '64%' },
+ { year: '2023', value: '1,39', height: '78%' },
+ { year: '2024', value: '1,52', height: '85%' },
+ { year: '2025', value: '1,79', height: '100%' },
+]
+
+export const trendChartLabel =
+ 'Рост числа пациентов медицинской реабилитации по ОМС в России с 1,14 миллиона в 2022 году до 1,79 миллиона в 2025 году'
+
+export const cabinetAsProcedures = [
+ 'аппараты работают разрозненно;',
+ 'одна услуга за визит и слабая пакетизация;',
+ 'назначения зависят от одного специалиста;',
+ 'нет контроля загрузки и завершения курса.',
+]
+
+export const cabinetAsSystem = [
+ 'существующие методы встроены в маршруты;',
+ 'EXO закрывает только выявленные пробелы;',
+ 'команда работает по единым картам и ролям;',
+ 'руководитель видит загрузку, результат и экономику.',
+]
+
+export const marketSources = [
+ {
+ label: 'WHO / IHME',
+ href: 'https://www.who.int/teams/noncommunicable-diseases/sensory-functions-disability-and-rehabilitation/global-estimates-of-the-need-for-rehabilitation',
+ },
+ {
+ label: 'Минздрав России',
+ href: 'https://minzdrav.gov.ru/news/2026/04/06/30625-zamglavy-minzdrava-rossii-evgeniy-kamkin-rasskazal-kak-izmenilas-sistema-meditsinskoy-reabilitatsii-v-rossii',
+ },
+ {
+ label: 'федеральный проект медицинской реабилитации',
+ href: 'https://minzdrav.gov.ru/poleznye-resursy/natsionalnye-proekty-rossii-prodolzhitelnaya-i-aktivnaya-zhizn-novye-tehnologii-sberezheniya-zdorovya/struktura-i-klyuchevye-meropriyatiya-federalnogo-proekta-optimalnaya-dlya-vosstanovleniya-zdorovya-meditsinskaya-reabilitatsiya',
+ },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Экономика действующего кабинета */
+/* -------------------------------------------------------------------------- */
+
+export const leakStages = [
+ { label: ['Не предложили', 'курс'], percent: '−35%' },
+ { label: ['Нет повторных', 'визитов'], percent: '−30%' },
+ { label: ['Нет регулярного', 'сопровождения'], percent: '−25%' },
+ { label: ['Нет комплексного', 'подхода'], percent: '−20%' },
+]
+
+export const leakBreakdown = [
+ { label: 'Не предложили курс (−35%)', value: '≈ 9 450 000 ₽' },
+ { label: 'Нет повторных визитов (−30%)', value: '≈ 6 750 000 ₽' },
+ { label: 'Нет регулярного сопровождения (−25%)', value: '≈ 2 970 000 ₽' },
+ { label: 'Нет комплексного подхода (−20%)', value: '≈ 810 000 ₽' },
+]
+
+export const leakSolutions = [
+ { icon: 'gear', title: 'Системная работа', text: 'Стандартизация процессов, назначений и скриптов.' },
+ { icon: 'clipboard', title: 'Курсовой подход', text: 'План лечения оформляется как понятный курс.' },
+ { icon: 'repeat', title: 'Повторные визиты', text: 'Контроль результата и плановое сопровождение пациента.' },
+ { icon: 'layers', title: 'Комплексные программы', text: 'Комбинация действующих методик и оборудования ЭКЗО.' },
+] as const
+
+export const revenueFormula = [
+ { value: '1 000', label: 'активных пациентов в базе за год' },
+ { value: '27 000 ₽', label: 'средний чек курса' },
+ { value: '4', label: 'цикла в год' },
+]
+
+export const revenueResult = {
+ value: '108 000 000 ₽',
+ label: 'дополнительной выручки в год без вложений в маркетинг',
+}
+
+export const revenueMetrics = [
+ { value: '+108 000 000 ₽', label: 'дополнительная выручка в год' },
+ { value: '60–70%', label: 'маржинальность услуг' },
+ { value: '0 ₽', label: 'дополнительных расходов на маркетинг' },
+ { value: '3–6 мес.', label: 'срок окупаемости внедрения' },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Сценарии выручки */
+/* -------------------------------------------------------------------------- */
+
+export const revenueScenarios = [
+ { courses: '30', revenue: '0,81 млн ₽', note: 'осторожный сценарий' },
+ { courses: '60', revenue: '1,62 млн ₽', note: 'рабочая загрузка' },
+ { courses: '100', revenue: '2,70 млн ₽', note: 'сильная загрузка' },
+]
+
+export const revenueDrivers = ['Загрузка кабинета', 'Доля курсов', 'Повторные визиты', 'Средний чек']
+
+/* -------------------------------------------------------------------------- */
+/* Модернизация */
+/* -------------------------------------------------------------------------- */
+
+export const promises = [
+ {
+ icon: 'load',
+ title: 'Загрузить действующее оборудование',
+ text: 'Вернуть полезным аппаратам точную роль, назначающих врачей, расписание и понятный курс.',
+ },
+ {
+ icon: 'gap',
+ title: 'Закрыть клинические пробелы',
+ text: 'Добавить только те EXO-модули, которых не хватает текущим врачебным маршрутам.',
+ },
+ {
+ icon: 'throughput',
+ title: 'Увеличить пропускную способность',
+ text: 'Развести активные и параллельные процедуры, сократить простои и собрать пакетные программы.',
+ },
+ {
+ icon: 'result',
+ title: 'Управлять результатом',
+ text: 'Измерять назначения, завершение курса, загрузку, динамику, повторные программы и экономику.',
+ },
+] as const
+
+export const profileChips = [
+ 'Травматология и ортопедия',
+ 'Неврология',
+ 'Послеоперационная реабилитация',
+ 'Спортивная медицина',
+ 'Ревматология',
+ 'Флебология / лимфология',
+ 'Гинекология / Урология',
+ 'Эстетическая медицина',
+]
+
+/* -------------------------------------------------------------------------- */
+/* Технологический конструктор */
+/* -------------------------------------------------------------------------- */
+
+export const devices = [
+ {
+ image: deviceTherapy,
+ alt: 'Аппарат ЭкзоТерапия',
+ kicker: 'Системное усиление',
+ title: 'ЭкзоТерапия',
+ indications: 'ОДА • неврология • дыхательная система • сосуды • органы малого таза • ЖКТ',
+ role: 'Высокоинтенсивная импульсная магнитотерапия.',
+ },
+ {
+ image: deviceTecar,
+ alt: 'Аппарат ЭкзоТекар 3 в 1',
+ kicker: 'Локальное ядро',
+ title: 'ЭкзоТекар 3 в 1',
+ indications: 'мышцы • суставы • связки • сухожилия • фасции • рубцы • посттравматическое восстановление',
+ role: 'Текар-терапия + ударно-волновая терапия + ультразвуковая терапия.',
+ },
+ {
+ image: deviceMagnet,
+ alt: 'Аппарат ЭкзоМагнит 3 в 1',
+ kicker: 'Многофакторный модуль',
+ title: 'ЭкзоМагнит 3 в 1',
+ indications: 'суставы • позвоночник • мышцы • сухожилия • мягкие ткани • малый таз',
+ role: 'Магнит высокой интенсивности + ударно-волновая терапия + инфракрасная терапия.',
+ },
+ {
+ image: devicePress,
+ alt: 'Аппарат ЭкзоПресс',
+ kicker: 'Параллельный поток',
+ title: 'ЭкзоПресс',
+ indications:
+ 'отёчные программы • лимфоотток • снятие тяжести в ногах • сосуды • послеоперационная реабилитация',
+ role: 'Компрессионная терапия + тепловая терапия + холодовая терапия.',
+ },
+ {
+ image: deviceHydrogen,
+ alt: 'Аппарат ЭкзоВодород',
+ kicker: 'Поддерживающий контур',
+ title: 'ЭкзоВодород',
+ indications:
+ 'системное восстановление • антиоксидантная терапия • улучшение метаболизма • поддержка иммунитета • антистресс',
+ role: 'Ингаляция молекулярным водородом',
+ },
+ {
+ image: deviceLaser,
+ alt: 'Аппарат ЭкзоЛазер B',
+ kicker: 'Локальные программы',
+ title: 'ЭкзоЛазер В',
+ indications:
+ 'мягкотканные травмы • точечное воспаление • регенерация тканей • болевые синдромы • реабилитация • стимуляция микроциркуляции • противоотёчный эффект • лечение связок и сухожилий • ускорение метаболизма',
+ role: 'Высокоинтенсивная лазерная терапия.',
+ },
+ {
+ image: deviceImpulse,
+ alt: 'Аппарат ЭкзоИмпульс',
+ kicker: 'Нейромышечный модуль',
+ title: 'ЭкзоИмпульс',
+ indications:
+ 'электромагнитная стимуляция • нервно-мышечная система • устранение спазмов и зажимов • активация регенерации • противовоспалительный эффект • микроциркуляция и лимфодренаж • снятие глубоких мышечных болей • восстановление двигательной активности • реабилитация при неврологических патологиях',
+ role: 'Фокусированная ударно-волновая терапия',
+ },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Комбинированные маршруты */
+/* -------------------------------------------------------------------------- */
+
+export const programs = [
+ {
+ num: '01',
+ title: 'Нейрореабилитация',
+ text: 'Наше оборудование помогает пациентам восстановить двигательные функции, в т.ч. после инсульта, снизить проявления спастичности и парезов, улучшить баланс и координацию.',
+ },
+ {
+ num: '02',
+ title: 'Травматология и ортопедия',
+ text: 'Устройства обеспечивают эффективную реабилитацию после переломов и эндопротезирования, способствуют снятию отёка и боли, повышают подвижность суставов и предупреждают развитие контрактур.',
+ },
+ {
+ num: '03',
+ title: 'Послеоперационное восстановление',
+ text: 'Оборудование позволяет активизировать пациентов в ранние сроки, стимулирует регенерацию тканей и снижает риск послеоперационных осложнений.',
+ },
+ {
+ num: '04',
+ title: 'Хронические боли и дегенеративные заболевания',
+ text: 'При остеохондрозе и артрозах оборудование помогает снизить болевой синдром и улучшить трофику и подвижность поражённых участков.',
+ },
+ {
+ num: '05',
+ title: 'Детская реабилитация',
+ text: 'Специальные методики способствуют развитию моторных навыков у детей с ДЦП, укрепляют мышечный корсет и помогают освоить вертикальное положение.',
+ },
+ {
+ num: '06',
+ title: 'Спортивная медицина',
+ text: 'Оборудование ускоряет восстановление спортсменов после травм и перегрузок, помогает грамотно вернуться к тренировкам и соревнованиям.',
+ },
+ {
+ num: '07',
+ title: 'Паллиативная поддержка',
+ text: 'Устройства облегчают хроническую боль и помогают сохранить функциональную активность на максимально возможном уровне.',
+ },
+]
+
+export const routeSteps = [
+ {
+ title: 'Запрос действующего пациента',
+ text: 'Боль, отёк, скованность, слабость или восстановление.',
+ },
+ { title: 'Назначение врача', text: 'Выбор физического фактора и исключение противопоказаний.' },
+ { title: 'Курс процедур', text: 'Действующие методы + EXO по этапу реабилитации.' },
+ { title: 'Контроль реакции', text: 'Самочувствие, движение, переносимость и динамика жалоб.' },
+ { title: 'Повтор / следующий этап', text: 'Поддерживающая программа или корректировка маршрута.' },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Модели усиления и пилот */
+/* -------------------------------------------------------------------------- */
+
+export const formats = [
+ {
+ area: 'от 12 м²',
+ title: 'Один кабинет',
+ text: 'Стартовый формат под отдельный сценарий и ограниченную конфигурацию.',
+ },
+ {
+ area: 'от 35 м²',
+ title: 'Два кабинета',
+ text: 'Базовая инфраструктура с разделением активных и параллельных процедур.',
+ },
+ {
+ area: 'от 45 м²',
+ title: 'Три кабинета',
+ text: 'Расширенный формат для нескольких маршрутов и большей пропускной способности.',
+ },
+]
+
+export const timeline = [
+ {
+ week: '1–2 неделя.',
+ title: 'Сбор данных и комплексный аудит кабинета',
+ lead: 'Мы проводим глубокий технический аудит текущего оборудования. Анализируем действующее направление по нозологиям, сроки лечения и методики.',
+ items: [
+ {
+ title: 'Инвентаризация и аудит оборудования',
+ text: 'Проверка технического состояния, износа и реальной загрузки каждого действующего аппарата клиники.',
+ },
+ {
+ title: 'Анализ расписания и логистики',
+ text: 'Поиск «узких мест» в сетке записи, из-за которых простаивают кабинеты и формируются простои у врачей.',
+ },
+ {
+ title: 'Экспертиза документов',
+ text: 'Проверка действующих медицинских лицензий, соответствия стандартам оснащения Минздрава и текущих карт назначений.',
+ },
+ {
+ title: 'Анализ штата и мотивации',
+ text: 'Оценка квалификации врачей и медсестёр, анализ их загрузки и текущей схемы оплаты труда.',
+ },
+ {
+ title: 'Оцифровка экономики и потока',
+ text: 'Расчёт стоимости одного визита пациента, маржинальности отдельных процедур и объёма упущенной прибыли клиники.',
+ },
+ ],
+ },
+ {
+ week: '3–4 неделя.',
+ title: 'Разработка карты пробелов и проектирование EXO-маршрутов',
+ lead: 'На основе аудита мы создаём индивидуальное инженерное и медицинское решение под специфику вашей клиники.',
+ items: [
+ { title: 'План по увеличению нагрузки на действующие аппараты' },
+ { title: 'План по увеличению пропускной способности одного кабинета' },
+ { title: 'Формирование индивидуальных комплексных методик' },
+ { title: 'План перезонирования' },
+ ],
+ },
+ {
+ week: '5–6 неделя.',
+ title: 'Бесшовное дооснащение и комплексное обучение команды',
+ lead: 'Мы интегрируем оборудование и готовим команду к новой модели работы без остановки текущего приёма пациентов. Все технические и образовательные процессы подстраиваются под график вашей клиники.',
+ items: [
+ {
+ title: 'Бесшовный монтаж и калибровка',
+ text: 'Установка модулей производится в удобное для вас время, включая выходные или вечерние часы. Клиника продолжает принимать пациентов в штатном режиме — вы не теряете ни одного дня выручки.',
+ },
+ {
+ title: 'Гибкий формат обучения персонала',
+ text: 'Мы подбираем комфортный график занятий без отрыва сотрудников от работы. Дополнительно доступна опция обучения на базе нашей действующей клиники.',
+ },
+ {
+ title: 'Внедрение технологических карт',
+ text: 'Интеграция готовых протоколов лечения в МИС клиники для быстрой работы врачей.',
+ },
+ {
+ title: 'Обучение врачей',
+ text: 'Глубокий курс по сочетанным методикам EXO-терапии, биомеханике, оценке динамики пациента и показаниям для курсового лечения.',
+ },
+ {
+ title: 'Инструктаж медицинских сестёр',
+ text: 'Практическая отработка навыков проведения параллельных процедур и контроля безопасности.',
+ },
+ {
+ title: 'Подготовка администраторов',
+ text: 'Обучение сервисного персонала работе со скриптами, алгоритмам удержания пациентов и правилам презентации комплексных пакетов.',
+ },
+ ],
+ },
+ {
+ week: '7–8 неделя.',
+ title: 'Мягкий перезапуск, запуск пакетов и аналитика',
+ lead: 'Запуск обновлённого кабинета в работу, перевод текущих пациентов на новые маршруты и фиксация первых финансовых результатов.',
+ items: [
+ {
+ title: 'Работа с действующими пациентами',
+ text: 'Мягкий перевод пациентов с разовых процедур на новые комбинированные EXO-программы.',
+ },
+ {
+ title: 'Старт продаж новых пакетов услуг',
+ text: 'Внедрение высокомаржинальных курсовых продуктов вместо неэффективной поштучной продажи визитов.',
+ },
+ {
+ title: 'Внедрение контроля «до / после»',
+ text: 'Запуск системы объективной оценки результатов лечения: снимки, тесты и шкалы боли.',
+ },
+ {
+ title: 'Аналитика первой прибыли',
+ text: 'Оценка динамики загрузки кабинета, роста среднего чека и удовлетворённости пациентов за первые 14 дней работы.',
+ },
+ {
+ title: 'Дорожная карта по увеличению целевой аудитории',
+ text: 'План расширения спектра оказываемых услуг и дальнейшего развития кабинета.',
+ },
+ ],
+ },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Почему Экзо Групп */
+/* -------------------------------------------------------------------------- */
+
+export const whyItems = [
+ {
+ icon: 'audit',
+ title: 'Аудит вместо типовой закупки',
+ text: 'Оцениваем парк, документы, загрузку, назначения и клинические пробелы до формирования комплектации.',
+ },
+ {
+ icon: 'clinic',
+ title: 'Собственная клиническая практика',
+ text: 'Оборудование, маршруты и организация работы проверяются внутри сети Экзо Клиник.',
+ },
+ {
+ icon: 'roles',
+ title: 'Обучение по ролям',
+ text: 'Врачи назначают, медсёстры выполняют, главный врач контролирует, администратор доводит пациента до курса.',
+ },
+] as const
+
+export const companyStats = [
+ { value: '100+', label: 'точек установки' },
+ { value: '60+', label: 'медицинских учреждений' },
+ { value: '60 дней', label: 'до модели «до / после»' },
+]
+
+/* -------------------------------------------------------------------------- */
+/* Заявка */
+/* -------------------------------------------------------------------------- */
+
+export const ctaChecks = [
+ 'аудит действующего оборудования и решение по каждому аппарату;',
+ 'EXO-конфигурация только под выявленные пробелы;',
+ 'план пилота на 60 дней и KPI «до / после».',
+]
+
+export const cabinetStateOptions = [
+ 'Работает, но низкая загрузка',
+ 'Старое оборудование / часть простаивает',
+ 'Современные аппараты работают разрозненно',
+ 'Нужно расширить клинические возможности',
+ 'Нужна единая модель для сети',
+ 'Другое',
+]
+
+export const profileOptions = [
+ 'Многопрофильный медицинский центр',
+ 'Ортопедия / неврология',
+ 'Реабилитация / ЛФК / спорт',
+ 'Флебология / лимфология',
+ 'Женское / мужское здоровье',
+ 'Кардиология / пульмонология',
+ 'Другое',
+]
+
+/* -------------------------------------------------------------------------- */
+/* Резидентские статусы */
+/* -------------------------------------------------------------------------- */
+
+export const residencies = [
+ {
+ href: 'https://isamara.ru/zhiguli-valley/',
+ label: 'Технопарк Жигулёвская долина',
+ width: 340,
+ height: 93,
+ },
+ { href: 'https://sk.ru/', label: 'Участник проекта Сколково', width: 330, height: 88 },
+]
diff --git a/medcenter/src/hooks/useReveal.ts b/medcenter/src/hooks/useReveal.ts
new file mode 100644
index 0000000..ce58032
--- /dev/null
+++ b/medcenter/src/hooks/useReveal.ts
@@ -0,0 +1,32 @@
+import { useEffect, useRef, useState } from 'react'
+
+/**
+ * Scroll-in animation, matching the original page: fires once at 12% visibility
+ * and then stops observing. The `.reveal` / `.is-visible` pair lives in CSS so
+ * that `prefers-reduced-motion` can neutralise it in one place.
+ */
+export function useReveal() {
+ const ref = useRef(null)
+ const [visible, setVisible] = useState(false)
+
+ useEffect(() => {
+ const element = ref.current
+ if (!element || visible) return
+
+ const observer = new IntersectionObserver(
+ (entries) => {
+ for (const entry of entries) {
+ if (!entry.isIntersecting) continue
+ setVisible(true)
+ observer.unobserve(entry.target)
+ }
+ },
+ { threshold: 0.12 },
+ )
+
+ observer.observe(element)
+ return () => observer.disconnect()
+ }, [visible])
+
+ return { ref, visible, revealClass: visible ? 'reveal is-visible' : 'reveal' }
+}
diff --git a/medcenter/src/index.css b/medcenter/src/index.css
new file mode 100644
index 0000000..4cb6100
--- /dev/null
+++ b/medcenter/src/index.css
@@ -0,0 +1,396 @@
+@import "tailwindcss";
+
+/* ---------------------------------------------------------------------------
+ Design tokens — ported 1:1 from the :root block of the original landing.
+ The default Tailwind palette and breakpoints are cleared so that only the
+ EXO design system is reachable from utility classes.
+--------------------------------------------------------------------------- */
+@theme {
+ --color-*: initial;
+ --color-transparent: transparent;
+ --color-current: currentColor;
+ --color-white: #ffffff;
+ --color-black: #000000;
+
+ /* Brand */
+ --color-navy: #0a2540;
+ --color-navy-deep: #061b2f;
+ --color-navy-3: #0e3352;
+ --color-navy-4: #0e3b5b;
+ --color-teal: #00c4b4;
+ --color-teal-bright: #45e4d7;
+ --color-teal-deep: #00a99a;
+ --color-teal-ink: #008f84;
+ --color-ice: #eafbf8;
+
+ /* Surfaces & text */
+ --color-paper: #f5fafb;
+ --color-ink: #0a2540;
+ --color-muted: #60778b;
+ --color-footer: #041524;
+ /* The dark "сценарии выручки" band sits between navy and navy-deep. */
+ --color-scenario: #071f35;
+
+ /* Radii */
+ --radius-md: 18px;
+ --radius-lg: 25px;
+ --radius-xl: 34px;
+
+ /* Elevation */
+ --shadow-deep: 0 30px 90px rgb(4 30 48 / 0.16);
+ --shadow-soft: 0 18px 55px rgb(3 26 43 / 0.08);
+
+ /* Layout rhythm */
+ --container-page: 1200px;
+ --spacing-section: clamp(68px, 8vw, 108px);
+ --spacing-section-compact: clamp(58px, 6vw, 84px);
+
+ /* Breakpoints — the original used 600 / 760 / 980 */
+ --breakpoint-*: initial;
+ --breakpoint-sm: 600px;
+ --breakpoint-md: 760px;
+ --breakpoint-lg: 980px;
+
+ /* "Inter Variable" is the family Fontsource registers; the rest of the chain
+ is the original stack, kept for the swap window and for the few glyphs
+ (≈ − ×) that Inter's subsets do not carry. */
+ --font-sans: "Inter Variable", Inter, Manrope, "Segoe UI", Arial, sans-serif;
+}
+
+/* The original's `max-width` queries do not line up with the min-width scale
+ above; they are exposed as named variants instead of arbitrary values so the
+ intent stays readable in the markup. Declared widest-first: Tailwind emits
+ variants in registration order, so a narrower one must come later to win. */
+@custom-variant stack (@media (max-width: 1050px));
+@custom-variant narrow (@media (max-width: 760px));
+@custom-variant compact (@media (max-width: 560px));
+@custom-variant phone (@media (max-width: 520px));
+@custom-variant tiny (@media (max-width: 430px));
+
+@layer base {
+ html {
+ scroll-behavior: smooth;
+ background: var(--color-navy-deep);
+ }
+
+ body {
+ background-color: var(--color-paper);
+ color: var(--color-ink);
+ font-family: var(--font-sans);
+ font-size: 16px;
+ line-height: 1.55;
+ -webkit-font-smoothing: antialiased;
+ text-rendering: optimizeLegibility;
+ overflow-x: hidden;
+ }
+
+ /* The fixed header is 78px tall; anchors must clear it. */
+ section[id] {
+ scroll-margin-top: 78px;
+ }
+
+ ::selection {
+ background: rgb(0 196 180 / 0.28);
+ color: var(--color-navy);
+ }
+
+ /* Preflight zeroes the type scale; the original relied on these exact values
+ for every heading on the page, so they are restored once, here. */
+ h1,
+ h2,
+ h3 {
+ text-wrap: balance;
+ }
+
+ h1 {
+ margin-bottom: 22px;
+ max-width: 940px;
+ font-size: clamp(42px, 7.7vw, 84px);
+ font-weight: 790;
+ line-height: 0.98;
+ letter-spacing: -0.055em;
+ }
+
+ h2 {
+ margin-bottom: 20px;
+ font-size: clamp(34px, 5vw, 58px);
+ font-weight: 760;
+ line-height: 1.03;
+ letter-spacing: -0.045em;
+ }
+
+ h3 {
+ margin-bottom: 10px;
+ font-size: clamp(21px, 2.4vw, 28px);
+ font-weight: bold;
+ line-height: 1.14;
+ letter-spacing: -0.025em;
+ }
+
+ h4 {
+ font-weight: bold;
+ }
+
+ button,
+ a {
+ -webkit-tap-highlight-color: transparent;
+ }
+}
+
+@layer components {
+ /* Scroll-triggered entrance. A class rather than utilities because it is
+ applied to ~40 elements and toggled from a shared IntersectionObserver. */
+ .reveal {
+ opacity: 0;
+ transform: translateY(24px);
+ transition:
+ opacity 0.7s ease,
+ transform 0.7s cubic-bezier(0.2, 0.65, 0.3, 1);
+ }
+
+ .reveal.is-visible {
+ opacity: 1;
+ transform: none;
+ }
+
+ /* Card rows that scroll horizontally on phones. Every section uses the same
+ mechanics and only differs in the card width and in the breakpoint where
+ the row becomes a plain grid — that part is applied per section with
+ `sm:grid-still` / `md:grid-still` and `auto-cols-*`. */
+ .scroll-cards {
+ display: grid;
+ grid-auto-flow: column;
+ overflow-x: auto;
+ overscroll-behavior-inline: contain;
+ scroll-snap-type: inline mandatory;
+ scrollbar-width: none;
+ padding: 2px 16px 15px;
+ margin-inline: -16px;
+ }
+
+ .scroll-cards::-webkit-scrollbar {
+ display: none;
+ }
+
+ .scroll-cards > * {
+ scroll-snap-align: start;
+ }
+
+ /* Hero backdrop: two stacked scrims. The horizontal one is pushed further
+ right from 980px up, where the layout gains room. */
+ .hero-scrim {
+ background:
+ linear-gradient(
+ 90deg,
+ rgb(4 24 41 / 0.98) 0%,
+ rgb(5 28 47 / 0.92) 40%,
+ rgb(5 28 47 / 0.38) 76%,
+ rgb(5 28 47 / 0.14) 100%
+ ),
+ linear-gradient(0deg, rgb(3 20 34 / 0.78), transparent 48%);
+ }
+
+ @media (min-width: 980px) {
+ .hero-scrim {
+ background:
+ linear-gradient(
+ 90deg,
+ rgb(4 24 41 / 0.99) 0%,
+ rgb(5 28 47 / 0.93) 42%,
+ rgb(5 28 47 / 0.3) 74%,
+ rgb(5 28 47 / 0.1) 100%
+ ),
+ linear-gradient(0deg, rgb(3 20 34 / 0.75), transparent 50%);
+ }
+ }
+
+ /* The hero photo, anchored to its right edge so that the logo printed on the
+ equipment stays clear of the copy at every width. */
+ .hero-photo {
+ background-position: 100% center;
+ background-size: cover;
+ }
+
+ @media (max-width: 980px) {
+ .hero-photo {
+ background-position: 96% center;
+ }
+ }
+
+ @media (max-width: 640px) {
+ .hero-photo {
+ background-position: 94% center;
+ }
+ }
+
+ /* Soft teal bloom used behind cards and panels, in four sizes/positions. */
+ .teal-bloom {
+ background: radial-gradient(circle, rgb(0 196 180 / 0.22), transparent 67%);
+ }
+
+ .teal-bloom-soft {
+ background: radial-gradient(circle, rgb(0 196 180 / 0.17), transparent 68%);
+ }
+
+ .gap-card-surface {
+ background: linear-gradient(145deg, var(--color-navy), #0c3650);
+ }
+
+ .system-panel-surface {
+ background: linear-gradient(145deg, #ffffff, #f2fbfa);
+ }
+
+ .equipment-card-surface {
+ background: linear-gradient(155deg, rgb(255 255 255 / 0.1), rgb(255 255 255 / 0.045));
+ }
+
+ .equipment-media-surface {
+ background: radial-gradient(circle at 50% 42%, rgb(0 196 180 / 0.15), rgb(3 22 38 / 0.16) 46%, rgb(3 22 38 / 0.64) 100%);
+ }
+
+ .loss-section-surface {
+ background: linear-gradient(180deg, #f8fcfd 0%, #eef8f8 100%);
+ }
+
+ .loss-panel-surface {
+ background: linear-gradient(145deg, #08253f 0%, #061b2f 100%);
+ }
+
+ .loss-anchor-surface {
+ background: linear-gradient(180deg, rgb(7 58 83 / 0.98), rgb(5 35 58 / 0.98));
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.06);
+ }
+
+ .loss-solution-surface {
+ background: linear-gradient(180deg, #ffffff, #f5fbfb);
+ }
+
+ .loss-result-surface {
+ background: linear-gradient(135deg, #00b9aa, #00cfc0);
+ }
+
+ /* The horizontal pipe the four leak stages sit on. Its metallic sheen is a
+ five-stop gradient, so it stays a class rather than an arbitrary value. */
+ .loss-pipe {
+ background: linear-gradient(180deg, #eff8fa 0%, #9fbbc4 45%, #dcecef 55%, #547986 100%);
+ box-shadow:
+ 0 0 15px rgb(69 228 215 / 0.25),
+ inset 0 1px 1px rgb(255 255 255 / 0.8);
+ }
+
+ /* A drain hole with a droplet falling out of it. */
+ .loss-hole {
+ background: radial-gradient(
+ circle at 50% 42%,
+ #061b2f 0 34%,
+ #5f7e88 36% 48%,
+ #d9e9eb 50% 65%,
+ #6c8c96 67% 100%
+ );
+ box-shadow: 0 0 12px rgb(69 228 215 / 0.32);
+ }
+
+ .loss-hole::after {
+ content: "";
+ position: absolute;
+ left: 50%;
+ top: 36px;
+ width: 9px;
+ height: 14px;
+ transform: translateX(-50%) rotate(45deg);
+ border-radius: 65% 35% 65% 35%;
+ background: linear-gradient(135deg, #e9fbff, #6da7b7);
+ box-shadow: 0 5px 12px rgb(0 196 180 / 0.22);
+ }
+
+ .cta-surface {
+ background:
+ radial-gradient(circle at 20% 20%, rgb(0 196 180 / 0.18), transparent 33%),
+ radial-gradient(circle at 90% 100%, rgb(37 117 151 / 0.26), transparent 39%),
+ var(--color-navy-deep);
+ }
+
+ .revenue-cta-surface {
+ background: linear-gradient(135deg, rgb(0 196 180 / 0.1), rgb(255 255 255 / 0.035));
+ }
+
+ .residency-surface {
+ background: linear-gradient(180deg, #071d31 0%, #041524 100%);
+ }
+
+ /* Market trend bars: they grow once the surrounding reveal turns visible. */
+ .trend-bar {
+ background: linear-gradient(180deg, var(--color-teal-bright), var(--color-teal));
+ box-shadow: 0 10px 24px rgb(0 196 180 / 0.2);
+ transform: scaleY(0);
+ transform-origin: bottom;
+ transition: transform 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
+ }
+
+ .is-visible .trend-bar {
+ transform: scaleY(1);
+ }
+
+ /* The