diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..6c10e4351
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+docs/desktop-regression/screenshots/** linguist-generated=true
diff --git a/docs/desktop-regression/PR.md b/docs/desktop-regression/PR.md
new file mode 100644
index 000000000..b4955442d
--- /dev/null
+++ b/docs/desktop-regression/PR.md
@@ -0,0 +1,144 @@
+
+
+## Что изменено
+
+UI Kit после #401 менял desktop layout, карточки, типографику и расположение действий. При ширине ≥1000 px восстановлена композиция dev до merge #401; mobile/tablet <1000 px сохраняет адаптив и исправления мобильной компоновки, включая светлую нейтральную шапку.
+
+## Зачем
+
+Существующий desktop не должен меняться при responsive/UI Kit миграции. Эталон: **5fe4d5c6db435488fffa688d0fa6bd713d6eb7a0**, первый родитель merge #401. Mobile-эталон для этой проверки: **1138fe0cad35a90551be8451b2b2df0d24aacd8f**.
+
+## Реализация
+
+- Responsive/UI Kit styles, Card/Field/Form/Filters adapters и общие geometry rules ограничены <1000 px. Desktop Button/Avatar/Icon/PageHeader и consumer styles сохраняют прежние размеры, Mont, отступы и сетки.
+- Office, Feed/FeedFilter, проекты/InfoCard, Programs/ProgramCard, Detail профиля/проекта/программы, Members, Vacancies, Courses и оба редактора восстановлены по desktop-эталону.
+- DesktopLayoutService управляет presentation-границей. Корни страниц/router outlets, поиск и формы сохраняются при resize; изменяется нужная presentation-разметка.
+- Mobile: ровные Detail actions и metadata, компактные карточки, activity над списком, работающие категории, полные навыки и читаемая география программы.
+- Pixel comparison gate проверяет **точное RGB совпадение и размеры**; overflow является отдельной проверкой.
+
+## API
+
+Не менялся. **Бизнес-логика не изменена**: нет diff в API/domain/infrastructure, DTO, payloads, routes, package/dependencies или backend. Прежние save/autosave/filter services, logout handler, IDs, role conditions, deadlines/status precedence сохранены.
+
+## UI
+
+Новый desktop-дизайн не вводился. [Отчёт и воспроизведение](https://github.com/PROCOLLAB-github/procollab/blob/fix/dev-mobile-ui-composition/docs/desktop-regression/README.md), [pixel results](https://github.com/PROCOLLAB-github/procollab/blob/fix/dev-mobile-ui-composition/docs/desktop-regression/comparison-desktop-after.json), [review / AC audit](https://github.com/PROCOLLAB-github/procollab/blob/fix/dev-mobile-ui-composition/docs/desktop-regression/review.md).
+
+Изменённые shared components: **Button, Icon, Avatar, Loader, Badge, Back, PageHeader, ProfileControlPanel, Tabs**, Card/Field/Form/Filters/Drawer/Dialog/Alert stylesheet adapters; social **Avatar adapter, Bar, Input, Select, Textarea, AutocompleteInput, Search, Checkbox, Dropdown, FileItem, Modal, Switch, Tag, UploadFile**; widgets **Detail, FeedFilter, InfoCard, VacancySkills/Status, ProjectsFilter/VacancyFilter, ProjectInviteDialog, ProjectVacancyCard/VacancyCard, News, RegionSelect, SkillsGroup/SpecializationsGroup, step navigation** и общие style mixins. [Полный список исходных файлов восстановления](https://github.com/PROCOLLAB-github/procollab/blob/fix/dev-mobile-ui-composition/docs/desktop-regression/source-files.json).
+
+Для прослеживаемости миграции #401 ниже сохранён её исходный список 80 переведённых шаблонов; это список этапа UI Kit, а не число файлов текущего восстановления.
+
+
+Все 80 переведённых HTML-шаблонов
+
+1. `projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.html`
+2. `projects/social_platform/src/app/ui/pages/auth/login/login.component.html`
+3. `projects/social_platform/src/app/ui/pages/auth/register/register.component.html`
+4. `projects/social_platform/src/app/ui/pages/auth/reset-password/reset-password.component.html`
+5. `projects/social_platform/src/app/ui/pages/auth/set-password/set-password.component.html`
+6. `projects/social_platform/src/app/ui/pages/courses/courses.component.html`
+7. `projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.html`
+8. `projects/social_platform/src/app/ui/pages/courses/list/course/course.component.html`
+9. `projects/social_platform/src/app/ui/pages/courses/list/list.component.html`
+10. `projects/social_platform/src/app/ui/pages/feed/feed.component.html`
+11. `projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html`
+12. `projects/social_platform/src/app/ui/pages/members/member-filters-dialog/member-filters-dialog.component.html`
+13. `projects/social_platform/src/app/ui/pages/members/members-filters/members-filters.component.html`
+14. `projects/social_platform/src/app/ui/pages/members/members.component.html`
+15. `projects/social_platform/src/app/ui/pages/office/nav/nav.component.html`
+16. `projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.html`
+17. `projects/social_platform/src/app/ui/pages/profile/edit/edit.component.html`
+18. `projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.html`
+19. `projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.html`
+20. `projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html`
+21. `projects/social_platform/src/app/ui/pages/program/detail/list/program-projects-filter/program-projects-filter.component.html`
+22. `projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/boolean-criterion/boolean-criterion.component.html`
+23. `projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.html`
+24. `projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/project-rating.component.html`
+25. `projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.html`
+26. `projects/social_platform/src/app/ui/pages/program/detail/register/register.component.html`
+27. `projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.html`
+28. `projects/social_platform/src/app/ui/pages/program/program.component.html`
+29. `projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.html`
+30. `projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-mid-side/projects-mid-side.component.html`
+31. `projects/social_platform/src/app/ui/pages/projects/detail/kanban/components/cancel-task-form/cancel-task-form.component.html`
+32. `projects/social_platform/src/app/ui/pages/projects/detail/kanban/components/create-board-form/create-board-form.component.html`
+33. `projects/social_platform/src/app/ui/pages/projects/detail/kanban/components/create-tag-form/create-tag-form.component.html`
+34. `projects/social_platform/src/app/ui/pages/projects/detail/kanban/components/task/detail/task-detail.component.html`
+35. `projects/social_platform/src/app/ui/pages/projects/detail/kanban/pages/archive/kanban-archive.component.html`
+36. `projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.html`
+37. `projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.html`
+38. `projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.html`
+39. `projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/collaborator-card/collaborator-card.component.html`
+40. `projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/invite-card/invite-card.component.html`
+41. `projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.html`
+42. `projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.html`
+43. `projects/social_platform/src/app/ui/pages/projects/edit/edit.component.html`
+44. `projects/social_platform/src/app/ui/pages/projects/list/list.component.html`
+45. `projects/social_platform/src/app/ui/pages/projects/projects.component.html`
+46. `projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.html`
+47. `projects/social_platform/src/app/ui/pages/vacancies/detail/info/info.component.html`
+48. `projects/social_platform/src/app/ui/pages/vacancies/list/list.component.html`
+49. `projects/social_platform/src/app/ui/pages/vacancies/vacancies.component.html`
+50. `projects/social_platform/src/app/ui/primitives/bar/bar.component.html`
+51. `projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.html`
+52. `projects/social_platform/src/app/ui/primitives/input/input.component.html`
+53. `projects/social_platform/src/app/ui/primitives/modal/modal.component.html`
+54. `projects/social_platform/src/app/ui/primitives/select/select.component.html`
+55. `projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.html`
+56. `projects/social_platform/src/app/ui/widgets/chat-window/chat-window.component.html`
+57. `projects/social_platform/src/app/ui/widgets/detail/detail.component.html`
+58. `projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.html`
+59. `projects/social_platform/src/app/ui/widgets/info-card/info-card.component.html`
+60. `projects/social_platform/src/app/ui/widgets/message-input/message-input.component.html`
+61. `projects/social_platform/src/app/ui/widgets/news-card/carousel/carousel.component.html`
+62. `projects/social_platform/src/app/ui/widgets/news-card/feed-news-modal/feed-news-modal.component.html`
+63. `projects/social_platform/src/app/ui/widgets/news-card/feed-news-preview/feed-news-preview.component.html`
+64. `projects/social_platform/src/app/ui/widgets/news-form/news-form.component.html`
+65. `projects/social_platform/src/app/ui/widgets/project-invite/profile-project-invite-modal.component.html`
+66. `projects/social_platform/src/app/ui/widgets/project-invite/project-invite-dialog.component.html`
+67. `projects/social_platform/src/app/ui/widgets/project-invite/project-invite-role-input.component.html`
+68. `projects/social_platform/src/app/ui/widgets/project-invite/project-member-invite-modal.component.html`
+69. `projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.html`
+70. `projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.html`
+71. `projects/social_platform/src/app/ui/widgets/region-select/region-select.component.html`
+72. `projects/social_platform/src/app/ui/widgets/skills-basket/skills-basket.component.html`
+73. `projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.html`
+74. `projects/social_platform/src/app/ui/widgets/vacancy-created-dialog/vacancy-created-dialog.component.html`
+75. `projects/social_platform/src/app/ui/widgets/vacancy-filter/vacancy-filter.component.html`
+76. `projects/ui/src/lib/components/primitives/avatar/avatar.component.html`
+77. `projects/ui/src/lib/components/primitives/back/back.component.html`
+78. `projects/ui/src/lib/components/primitives/button/button.component.html`
+79. `projects/ui/src/lib/components/primitives/icon/icon.component.html`
+80. `projects/ui/src/lib/components/primitives/loader/loader.component.html`
+
+
+
+## Permissions
+
+Не менялись. Existing guards/role conditions/server-owned permissions сохранены; server-side authorization заново не менялась и не аудировалась.
+
+## Проверки
+
+- [x] **Checked in browser:** 36 desktop пары (14 экранов + 3 empty states + loading action × 1440/1920), **0 отличающихся RGB-пикселей**. Повтор desktop эталона: 36/36, 0 пикселей. Без masks.
+- [x] **Checked in browser:** 42 mobile/tablet пары (14 экранов × 320/390/768), **0 отличающихся RGB-пикселей** относительно mobile-эталона.
+- [x] **Checked in browser:** 48 state checks (loading, empty, HTTP 500/retry, disabled, validation), 18 mobile interactions и 6 resize checks через 1000 px. Поиск/filter query/DOM routed roots сохраняются.
+- [x] **Checked by tests:** npm run test:ci — 2006 tests / 406 files. Три существующих runner exclusions сохранены.
+- [x] **Checked by build:** npm run build:social:prod — успешно, budgets не увеличены.
+- [x] **Checked by source/lint:** API/domain/infrastructure/dependencies diff пустой; ESLint 0 errors, 6 существующих warnings; SCSS проверен.
+
+## Acceptance criteria
+
+- [x] Desktop ≥1000 сохраняет legacy composition, shared styles не навязывают новую геометрию.
+- [x] Ключевые разделы проверены на 1440 и 1920 px **pixel/visual regression**, а не только overflow.
+- [x] Mobile/tablet 320/390/768 сохранён, states/interactions повторно проверены.
+- [x] API, permissions и бизнес-логика сохранены.
+
+## Не проверено
+
+- [ ] Реальные iOS/Android на dev-стенде после merge, перед prod. Доступа к физическим устройствам нет. Найденные проблемы — отдельными PR.
+- Полный live backend/role matrix и каждый скрытый scroll section/popup. Снимки фиксируют видимую композицию при viewport height 844 px; внутренний scroll Office не превращается в full-document screenshot. Desktop pixel states включают empty и loading action; остальные состояния проверены mobile state harness.
+
+## Риски / migration
+
+Два presentation-каскада сохраняют legacy desktop и responsive mobile, поэтому дальнейшие изменения shared styles требуют обеих pixel matrices. Build содержит Angular/template/CommonJS и component-size warnings, error budgets не увеличены. API/data migration не нужны. PR направлен в dev; production merge/deploy не входят в задачу. **READY TO MERGE INTO DEV** для реализации, device smoke-test остаётся этапом dev acceptance.
diff --git a/docs/desktop-regression/README.md b/docs/desktop-regression/README.md
new file mode 100644
index 000000000..7267a65b2
--- /dev/null
+++ b/docs/desktop-regression/README.md
@@ -0,0 +1,113 @@
+
+
+# Восстановление desktop после #401
+
+Desktop ≥1000 px возвращён к визуальному состоянию `dev` до merge #401.
+Mobile/tablet <1000 px сохраняет адаптив и исправления мобильной компоновки из #403.
+Новый desktop-дизайн в эту задачу не входит.
+
+- Desktop-эталон: `5fe4d5c6db435488fffa688d0fa6bd713d6eb7a0` — первый родитель merge
+ `ec57fa7cadb8ca7acef6859380a966a837783495` (#401).
+- Mobile-эталон: `1138fe0cad35a90551be8451b2b2df0d24aacd8f` — мобильные исправления #403 до восстановления desktop.
+- [Viewer](comparison.html), [desktop JSON](comparison-desktop-after.json),
+ [mobile JSON](comparison-mobile-after.json), [requirement audit](review.md).
+
+## Acceptance criteria
+
+1. Desktop сохраняет прежние layout, композицию, Mont, размеры, отступы и расположение действий.
+2. Office, Feed/FeedFilter, проекты/InfoCard, Programs/ProgramCard, Detail профиля/проекта/программы,
+ Members, Vacancies, Courses, PageHeader и shared Button/Card проверены на 1440 и 1920 px.
+3. **Pixel/visual regression — обязательный gate.** Размеры снимков и все RGB-пиксели должны совпадать.
+ Нет масок и разрешённых исключений. `compare.py --check` возвращает ошибку при любом отличии.
+ Дополнительная метрика `changedPixels` с допуском 8/255 помогает анализировать diff;
+ решение PASS использует строгую метрику `exactChangedPixels == 0`.
+4. Mobile/tablet сохраняется на 320, 390 и 768 px; проверяются состояния и взаимодействия.
+5. API, permissions, payloads, маршруты, бизнес-правила и зависимости сохраняются.
+
+## Результаты
+
+| Проверка | Результат |
+| -------------------------------------------------------------------- | ------------------------------------------------------------------ |
+| Повторный снимок desktop-эталона | 36/36, **0 отличающихся пикселей** |
+| Desktop до #401 vs исправление, 1440/1920 | 36/36, **0 отличающихся пикселей** |
+| Mobile до восстановления desktop vs исправление, 320/390/768 | 42/42, **0 отличающихся пикселей** |
+| Loading, empty, error/retry, disabled, validation и основные разделы | 48 mobile state checks |
+| Навигация, фильтры, навыки, карточки, активность и действия Detail | 18 mobile сценариев |
+| Переход 390 → 1000 → 768 → 390 | 6 checks: DOM routed roots, поиск и query фильтра сохраняются |
+| Unit tests | 2006 tests / 406 files; 3 существующих исключения runner сохранены |
+| Production build | Успешно, бюджеты не увеличены |
+| TypeScript lint | 0 errors, 6 существующих warnings |
+
+14 обычных экранов × 2 desktop-ширины + 3 empty-состояния × 2 ширины + loading action × 2 ширины = 36 пар.
+Mobile: 14 экранов × 3 ширины = 42 пары.
+
+Экраны: Feed/Office/FeedFilter, Projects dashboard, My projects, Members, Programs, Program Detail,
+Profile Detail, Project Detail, Vacancies, Vacancy Detail, Courses, Course Detail,
+Profile editor, Project editor. Desktop states: empty Feed, Vacancies, Courses и loading action урока.
+Все пары доступны в [viewer](comparison.html) и каталогах screenshots/desktop-before,
+screenshots/desktop-after, screenshots/mobile-before, screenshots/mobile-after.
+
+## Реализация и shared компоненты
+
+Новые responsive/UI Kit правила ограничены `<1000px`. Для desktop восстановлены прежние
+consumer styles и нужные фрагменты разметки. Общие `.ui-card`, `.ui-form`, `.ui-filters`,
+`.ui-field` и остальные адаптеры на desktop не задают новую геометрию.
+Нативные кнопки имеют нейтральный reset с нулевой specificity; размеры задают прежние consumers.
+
+`DesktopLayoutService` задаёт одну presentation-границу. Корни страниц, router outlets,
+поиск и формы сохраняются при изменении ширины; переключаются presentation-фрагменты.
+Desktop Avatar в social platform использует прежнюю рамку/обёртку, наследуя input API canonical Avatar.
+Стили полей сохраняют исходный порядок CSS: отступы модификаторов не перекрываются media-блоком.
+
+- `@uilib`: Button, Icon, Avatar, Loader, Badge, Back, PageHeader, ProfileControlPanel, Tabs;
+ DesktopLayoutService. Card/Field/Form/Filters/Drawer/Dialog/Alert adapters — scoped stylesheet.
+- Social primitives: Avatar compatibility adapter, Bar, Input, Select, Textarea, AutocompleteInput,
+ Search, Checkbox, Dropdown, FileItem, Modal, Switch, Tag, UploadFile.
+- Shared widgets: Detail, FeedFilter, InfoCard, VacancySkills/Status, ProjectsFilter/VacancyFilter,
+ ProjectInviteDialog, ProjectVacancyCard/VacancyCard, News components, RegionSelect,
+ SkillsGroup/SpecializationsGroup; общие typography/feed/vacancy/responsive mixins.
+- Step navigation проекта/профиля: прежняя desktop-разметка и мобильный Tabs ниже 1000 px.
+
+## Воспроизведение
+
+Нужны те же установленные зависимости, Playwright, Chrome, Python с Pillow и NumPy.
+`PLAYWRIGHT_MODULE` и `CHROME_PATH` указывают на установленный модуль и браузер.
+
+Собрать production из desktop-эталона, mobile-эталона и текущей ветки в отдельных каталогах.
+Раздавать их через `node docs/desktop-regression/serve.cjs `:
+desktop reference — 4431, mobile reference — 4432, исправление — 4433.
+Для state/interaction/resize scripts раздать исправление также на 4360.
+
+```powershell
+node docs/desktop-regression/capture.cjs desktop-before http://localhost:4431
+node docs/desktop-regression/capture.cjs desktop-repeat http://localhost:4431
+node docs/desktop-regression/capture.cjs desktop-after http://localhost:4433
+# Повторить для всех трёх desktop фаз:
+node docs/desktop-regression/capture.cjs desktop-before http://localhost:4431 1440,1920 edit
+node docs/desktop-regression/capture-states.cjs desktop-before http://localhost:4431
+node docs/desktop-regression/capture-loading.cjs desktop-before http://localhost:4431
+node docs/desktop-regression/capture.cjs mobile-before http://localhost:4432 320,390,768
+node docs/desktop-regression/capture.cjs mobile-after http://localhost:4433 320,390,768
+# Повторить для обеих mobile фаз:
+node docs/desktop-regression/capture.cjs mobile-before http://localhost:4432 320,390,768 edit
+python docs/desktop-regression/compare.py desktop-before desktop-repeat --check
+python docs/desktop-regression/compare.py desktop-before desktop-after --check
+python docs/desktop-regression/compare.py mobile-before mobile-after --check
+node docs/desktop-regression/states.cjs
+node docs/desktop-regression/interactions.cjs
+node docs/desktop-regression/resize.cjs
+npm run test:ci
+npm run build:social:prod
+npm run lint:ts
+```
+
+Синтетические API fixtures одинаковы для каждой пары, clock фиксирован, Mont загружен,
+animations/transitions отключены, браузер и device scale одинаковые. API запросы перехватываются;
+реальный backend не изменяется. Повтор эталона проверяет детерминизм.
+
+Снимки показывают видимую композицию при высоте viewport 844 px. Office использует внутренний
+scroll; `fullPage` не означает снимок всех скрытых областей scroll-контейнера. Динамический backend,
+все роли и все возможные данные этим набором не исчерпываются.
+
+Реальные iOS/Android на dev-стенде **не проверены**: нет доступа к физическим устройствам.
+После merge требуется device smoke-test перед prod; найденные проблемы — отдельными PR.
diff --git a/docs/desktop-regression/build.log b/docs/desktop-regression/build.log
new file mode 100644
index 000000000..0ce69b396
--- /dev/null
+++ b/docs/desktop-regression/build.log
@@ -0,0 +1,2454 @@
+
+> procollab@0.0.0 build:social:prod
+> npm run build:sprite && ng build social_platform --configuration=production
+
+
+> procollab@0.0.0 build:sprite
+> svg-sprite -s --dest=projects/social_platform/src/assets/icons "projects/social_platform/src/assets/icons/svg/**/*.svg"
+
+> Building...
+√ Building...
+Initial chunk files | Names | Raw size | Estimated transfer size
+chunk-3CG57ZN5.js | - | 435.93 kB | 73.95 kB
+chunk-EMX2ZQ7G.js | - | 213.04 kB | 60.81 kB
+main-O2SWNA4H.js | main | 207.24 kB | 53.23 kB
+styles-JB553RZJ.css | styles | 133.36 kB | 12.17 kB
+chunk-32JCLU4R.js | - | 111.30 kB | 28.30 kB
+chunk-FQQXBL2D.js | - | 83.07 kB | 25.83 kB
+chunk-V2IJE6ER.js | - | 72.83 kB | 16.82 kB
+chunk-YIH7FSUZ.js | - | 63.35 kB | 12.16 kB
+chunk-SEBII2ES.js | - | 42.79 kB | 8.66 kB
+chunk-DGTRQFRV.js | - | 29.13 kB | 5.34 kB
+chunk-Q6NJS6MG.js | - | 27.24 kB | 7.03 kB
+chunk-WYGUCQ2H.js | - | 11.43 kB | 2.59 kB
+chunk-DN3CBCVF.js | - | 8.34 kB | 2.56 kB
+chunk-JL552RI3.js | - | 4.30 kB | 1.19 kB
+chunk-J63M22RD.js | - | 4.04 kB | 1.47 kB
+chunk-N7P262YB.js | - | 3.19 kB | 1.27 kB
+chunk-GYIMPQDO.js | - | 3.02 kB | 1.14 kB
+chunk-JP4HTDU5.js | - | 1.47 kB | 386 bytes
+chunk-VOSPIT4N.js | - | 1.22 kB | 521 bytes
+chunk-UMKP35NR.js | - | 695 bytes | 695 bytes
+chunk-JHUOFMVX.js | - | 483 bytes | 483 bytes
+chunk-ZTXJLEZP.js | - | 474 bytes | 474 bytes
+chunk-IAS7Y3HI.js | - | 465 bytes | 465 bytes
+chunk-4WVOMZ3C.js | - | 352 bytes | 352 bytes
+chunk-Y7FCNQPS.js | - | 195 bytes | 195 bytes
+chunk-RQDRLMC2.js | - | 180 bytes | 180 bytes
+chunk-W2ZPBHP5.js | - | 160 bytes | 160 bytes
+chunk-N7PJCV3T.js | - | 128 bytes | 128 bytes
+chunk-DKVRXEF2.js | - | 127 bytes | 127 bytes
+chunk-PY5GJ2VA.js | - | 51 bytes | 51 bytes
+chunk-GDMD5RKS.js | - | 51 bytes | 51 bytes
+chunk-NCHAAQO5.js | - | 30 bytes | 30 bytes
+chunk-KTRLVWC3.js | - | 30 bytes | 30 bytes
+chunk-CRTRRB5R.js | - | 30 bytes | 30 bytes
+chunk-PKT6RRYE.js | - | 30 bytes | 30 bytes
+chunk-YIJ4Z6S4.js | - | 30 bytes | 30 bytes
+chunk-KEPWQ2XV.js | - | 30 bytes | 30 bytes
+chunk-FE3JRQRM.js | - | 30 bytes | 30 bytes
+chunk-GAELZNYR.js | - | 25 bytes | 25 bytes
+chunk-4CQUPGHG.js | - | 25 bytes | 25 bytes
+chunk-PPZSTFUD.js | - | 25 bytes | 25 bytes
+chunk-UYXSSEQD.js | - | 25 bytes | 25 bytes
+chunk-FI4DW6KU.js | - | 25 bytes | 25 bytes
+chunk-25HWN6II.js | - | 25 bytes | 25 bytes
+chunk-SVFKPVOL.js | - | 25 bytes | 25 bytes
+chunk-CRUTENDI.js | - | 0 bytes | 0 bytes
+chunk-S7EUWH5W.js | - | 0 bytes | 0 bytes
+
+ | Initial total | 1.46 MB | 319.19 kB
+
+Lazy chunk files | Names | Raw size | Estimated transfer size
+chunk-M3GFW3BB.js | detail-routes | 275.03 kB | 42.16 kB
+chunk-6VIOOPBT.js | onboarding-routes | 113.25 kB | 15.06 kB
+chunk-DGDJLME2.js | office-routes | 111.68 kB | 19.67 kB
+chunk-BEFPGAFR.js | detail-routes | 92.27 kB | 16.92 kB
+chunk-ACE7VP46.js | lesson-routes | 85.07 kB | 10.96 kB
+chunk-FKCA4C6N.js | - | 83.92 kB | 16.36 kB
+chunk-ZOBCXQ4X.js | projects-routes | 79.38 kB | 14.50 kB
+chunk-OM7RVM2H.js | - | 72.50 kB | 13.57 kB
+chunk-AJJJSWEY.js | index | 72.43 kB | 17.54 kB
+chunk-AMVSDNEL.js | auth-routes | 71.06 kB | 9.72 kB
+chunk-K5BP25SC.js | feed-routes | 47.71 kB | 7.69 kB
+chunk-JDJBBXO4.js | vacancies-detail-routes | 45.38 kB | 8.95 kB
+chunk-SXNPXFOC.js | profile-detail-routes | 40.98 kB | 7.75 kB
+chunk-BJAXUOYJ.js | course-detail-routes | 40.92 kB | 7.16 kB
+chunk-KBPUUHZY.js | project-team-step-component | 40.76 kB | 8.14 kB
+...and 88 more lazy chunks files. Use "--verbose" to show all the files.
+
+Application bundle generation complete. [23.899 seconds] - 2026-10-05T12:33:34.917Z
+
+▲ [WARNING] 23 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 1 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 6 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 3 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 32 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 4 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 4 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 3 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 24 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 9 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 3 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 12 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 5 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] 2 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] NG8113: BackComponent is not used within the template of CoursesComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/courses/courses.component.ts:19:4:
+ 19 │ BackComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:9:67:
+ 9 │ ...card__photo" [url]="member().personal?.avatar || ''" [size]="70" />
+ ╵ ~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:15:66:
+ 15 │ ...er-card__secondary" [title]="member().personal?.speciality || ''">
+ ╵ ~~~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:16:28:
+ 16 │ {{ member().personal?.speciality }}
+ ╵ ~~~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:17:30:
+ 17 │ @if (member().personal?.birthday; as birthday) {
+ ╵ ~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:18:30:
+ 18 │ {{ member().personal?.speciality ? " • " : "" }}{{ birth...
+ ╵ ~~~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: DialogFooterDirective is not used within the template of MemberFiltersDialogComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-filters-dialog/member-filters-dialog.component.ts:37:4:
+ 37 │ DialogFooterDirective,
+ ╵ ~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: ProfileInfoComponent is not used within the template of NavComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/office/nav/nav.component.ts:82:4:
+ 82 │ ProfileInfoComponent,
+ ╵ ~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: AlertDirective is not used within the template of SnackbarComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.ts:37:12:
+ 37 │ imports: [AlertDirective, CommonModule, IconComponent],
+ ╵ ~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.html:435:45:
+ 435 │ ... @if (achievements.at(i)?.get("title"); as title) {
+ ╵ ~~~
+
+ Warning occurs in the template of component OnboardingStageZeroComponent.
+
+ projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.ts:23:15:
+ 23 │ templateUrl: "./stage-zero.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8102: The left side of this nullish coalescing operation does not include 'null' or 'undefined' in its type, therefore the '??' operator can be safely removed. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.html:28:15:
+ 28 │ ... {{ user()!.personal.speciality ?? "не указана" }}
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Warning occurs in the template of component ProfileLeftSideComponent.
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.ts:23:15:
+ 23 │ templateUrl: "./profile-left-side.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: TruncatePipe is not used within the template of ProfileLeftSideComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.ts:25:78:
+ 25 │ ...RouterModule, IconComponent, YearsFromBirthdayPipe, TruncatePipe],
+ ╵ ~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: TruncatePipe is not used within the template of ProfileRightSideComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.ts:32:4:
+ 32 │ TruncatePipe,
+ ╵ ~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: UploadFileComponent is not used within the template of ProfileMainStepComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.ts:33:4:
+ 33 │ UploadFileComponent,
+ ╵ ~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html:95:52:
+ 95 │ ... [isSubscribed]="profileProjSubsIds()?.includes(listItem.id)"
+ ╵ ~~~~~~~~
+
+ Warning occurs in the template of component ProgramListComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.ts:40:15:
+ 40 │ templateUrl: "./list.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html:103:54:
+ 103 │ ... [isSubscribed]="profileProjSubsIds()?.includes(listItem.id)"
+ ╵ ~~~~~~~~
+
+ Warning occurs in the template of component ProgramListComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.ts:40:15:
+ 40 │ templateUrl: "./list.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.html:73:64:
+ 73 │ ...)!.isUserMember && program()!.links?.length && program()!.links) {
+ ╵ ~~~~~~
+
+ Warning occurs in the template of component ProgramDetailMainComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.ts:38:15:
+ 38 │ templateUrl: "./main.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.html:82:68:
+ 82 │ ... @if (program()!.isUserMember && program()!.materials?.length) {
+ ╵ ~~~~~~
+
+ Warning occurs in the template of component ProgramDetailMainComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.ts:38:15:
+ 38 │ templateUrl: "./main.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: BackComponent is not used within the template of ProgramComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/program.component.ts:22:4:
+ 22 │ BackComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: MessageInputComponent is not used within the template of ProjectChatComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/detail/chat/chat.component.ts:34:4:
+ 34 │ MessageInputComponent,
+ ╵ ~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.html:10:39:
+ 10 │ ... @if (achievements.at(i)?.get("title"); as achievementsName) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectAchievementStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.ts:17:15:
+ 17 │ templateUrl: "./project-achievement-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.html:315:32:
+ 315 │ @if (goals.at(i)?.get("title"); as goalName) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectMainStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.ts:39:15:
+ 39 │ templateUrl: "./project-main-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.html:331:32:
+ 331 │ @if (goals.at(i)?.get("completionDate"); as goalDat...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectMainStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.ts:39:15:
+ 39 │ templateUrl: "./project-main-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.html:353:32:
+ 353 │ @if (goals.at(i)?.get("responsible"); as goalLeader) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectMainStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.ts:39:15:
+ 39 │ templateUrl: "./project-main-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:11:37:
+ 11 │ @if (partners.at(i)?.get("name"); as name) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:27:37:
+ 27 │ @if (partners.at(i)?.get("inn"); as inn) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:46:35:
+ 46 │ ... @if (partners.at(i)?.get("contribution"); as contribut...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:63:35:
+ 63 │ ... @if (partners.at(i)?.get("decisionMaker"); as decision...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:116:36:
+ 116 │ @if (resources.at(i)?.get("type"); as type) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:133:36:
+ 133 │ ... @if (resources.at(i)?.get("description"); as descripti...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:150:36:
+ 150 │ ... @if (resources.at(i)?.get("partnerCompany"); as partne...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8109: isFilterOpen is a function and should be invoked: isFilterOpen() [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/projects.component.html:118:73:
+ 118 │ ...="filter page__filter" [class.page__filter--open]="isFilterOpen">
+ ╵ ~~~~~~~~~~~~
+
+ Warning occurs in the template of component ProjectsComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/projects.component.ts:33:15:
+ 33 │ templateUrl: "./projects.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-left-side/vacancies-left-side.component.html:7:29:
+ 7 │ @if (item.description?.trim()) {
+ ╵ ~~~~
+
+ Warning occurs in the template of component VacanciesLeftSideComponent.
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-left-side/vacancies-left-side.component.ts:9:15:
+ 9 │ templateUrl: "./vacancies-left-side.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.html:57:23:
+ 57 │ @if (item.project?.links?.length) {
+ ╵ ~~~~~
+
+ Warning occurs in the template of component VacanciesRightSideComponent.
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.ts:14:15:
+ 14 │ templateUrl: "./vacancies-right-side.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: BackComponent is not used within the template of VacanciesComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/vacancies/vacancies.component.ts:27:4:
+ 27 │ BackComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: CardDirective is not used within the template of NewsCardComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/widgets/news-card/news-card.component.ts:58:4:
+ 58 │ CardDirective,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/auth/login/login.component.scss:29:4:
+ 29 │ padding-left: 10px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss:14:2:
+ 14 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss:15:2:
+ 15 │ width: 100%;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss:16:2:
+ 16 │ max-width: 333px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss:17:2:
+ 17 │ overflow: hidden;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss:18:2:
+ 18 │ cursor: pointer;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss:16:2:
+ 16 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss:17:2:
+ 17 │ box-sizing: border-box;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss:18:2:
+ 18 │ display: block;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss:19:2:
+ 19 │ width: 156px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss:20:2:
+ 20 │ height: 248px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss:42:4:
+ 42 │ max-width: responsive.$container-md;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss:42:4:
+ 42 │ max-width: responsive.$container-md;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss:42:4:
+ 42 │ max-width: responsive.$container-md;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss:42:4:
+ 42 │ max-width: responsive.$container-md;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss:42:4:
+ 42 │ max-width: responsive.$container-md;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/office.component.scss:51:4:
+ 51 │ align-items: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/office.component.scss:51:4:
+ 51 │ align-items: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/office.component.scss:51:4:
+ 51 │ align-items: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/office.component.scss:52:4:
+ 52 │ justify-content: space-between;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/office/office.component.scss:52:4:
+ 52 │ justify-content: space-between;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss:295:2:
+ 295 │ max-height: calc(100vh - 40px);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss:295:2:
+ 295 │ max-height: calc(100vh - 40px);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss:295:2:
+ 295 │ max-height: calc(100vh - 40px);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss:295:2:
+ 295 │ max-height: calc(100vh - 40px);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss:305:2:
+ 305 │ overflow-y: auto;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/detail/team/team.component.scss:28:6:
+ 28 │ row-gap: 48px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss:24:2:
+ 24 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss:153:2:
+ 153 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss:154:2:
+ 154 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss:155:2:
+ 155 │ align-items: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss:156:2:
+ 156 │ justify-content: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss:157:2:
+ 157 │ width: 80%;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss:43:4:
+ 43 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss:43:4:
+ 43 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss:44:4:
+ 44 │ margin-top: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss:44:4:
+ 44 │ margin-top: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss:73:4:
+ 73 │ line-height: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss:81:2:
+ 81 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss:81:2:
+ 81 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss:82:2:
+ 82 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss:82:2:
+ 82 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss:83:2:
+ 83 │ gap: 16px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss:21:4:
+ 21 │ margin-bottom: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss:21:4:
+ 21 │ margin-bottom: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss:72:4:
+ 72 │ line-height: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss:72:4:
+ 72 │ line-height: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss:53:4:
+ 53 │ line-height: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss:53:4:
+ 53 │ line-height: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss:54:8:
+ 54 │ + &_arrow {
+ ╵ ^
+
+
+ The selector "+ .field__input-slim:focus_arrow" is invalid CSS.
+ This will be an error in Dart Sass 2.0.0.
+
+ More info: https://sass-lang.com/d/bogus-combinators
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss:57:10:
+ 57 │ i {
+ ╵ ^
+
+
+ The selector "+ .field__input-slim:focus_arrow i" is invalid CSS.
+ This will be an error in Dart Sass 2.0.0.
+
+ More info: https://sass-lang.com/d/bogus-combinators
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss:271:8:
+ 271 │ +&_arrow {
+ ╵ ^
+
+
+ The selector "+ .field__input-slim:focus_arrow" is invalid CSS.
+ This will be an error in Dart Sass 2.0.0.
+
+ More info: https://sass-lang.com/d/bogus-combinators
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss:274:10:
+ 274 │ i {
+ ╵ ^
+
+
+ The selector "+ .field__input-slim:focus_arrow i" is invalid CSS.
+ This will be an error in Dart Sass 2.0.0.
+
+ More info: https://sass-lang.com/d/bogus-combinators
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss:11:2:
+ 11 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss:12:2:
+ 12 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss:13:2:
+ 13 │ align-items: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss:14:2:
+ 14 │ justify-content: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss:15:2:
+ 15 │ width: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:76:4:
+ 76 │ background: var(--white);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:76:4:
+ 76 │ background: var(--white);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:76:4:
+ 76 │ background: var(--white);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:76:4:
+ 76 │ background: var(--white);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:76:4:
+ 76 │ background: var(--white);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/tag/tag.component.scss:11:2:
+ 11 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/tag/tag.component.scss:12:2:
+ 12 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/tag/tag.component.scss:13:2:
+ 13 │ align-items: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/tag/tag.component.scss:14:2:
+ 14 │ justify-content: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/tag/tag.component.scss:15:2:
+ 15 │ width: 100%;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss:60:6:
+ 60 │ border-radius: var(--ui-radius-card);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss:60:6:
+ 60 │ border-radius: var(--ui-radius-card);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss:60:6:
+ 60 │ border-radius: var(--ui-radius-card);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss:60:6:
+ 60 │ border-radius: var(--ui-radius-card);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss:60:6:
+ 60 │ border-radius: var(--ui-radius-card);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss:12:4:
+ 12 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss:13:4:
+ 13 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss:14:4:
+ 14 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss:15:4:
+ 15 │ width: 156px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss:96:4:
+ 96 │ width: 100%;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/news-card/feed-news-preview/feed-news-preview.component.scss:16:2:
+ 16 │ cursor: pointer;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss:19:2:
+ 19 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss:19:2:
+ 19 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss:19:2:
+ 19 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss:20:2:
+ 20 │ flex: 1;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss:20:2:
+ 20 │ flex: 1;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.scss:17:2:
+ 17 │ display: flex;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.scss:18:2:
+ 18 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.scss:19:2:
+ 19 │ gap: 16px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.scss:20:2:
+ 20 │ height: 100%;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-created-dialog/vacancy-created-dialog.component.scss:52:4:
+ 52 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-created-dialog/vacancy-created-dialog.component.scss:52:4:
+ 52 │ flex-direction: column;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-created-dialog/vacancy-created-dialog.component.scss:53:4:
+ 53 │ margin-top: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-created-dialog/vacancy-created-dialog.component.scss:53:4:
+ 53 │ margin-top: 20px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.scss:33:4:
+ 33 │ padding: 4px 10px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.scss:33:4:
+ 33 │ padding: 4px 10px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.scss:34:4:
+ 34 │ font: inherit;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.scss:34:4:
+ 34 │ font: inherit;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.scss:44:4:
+ 44 │ line-height: 18px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/ui/src/lib/components/primitives/button/button.component.scss:44:2:
+ 44 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/ui/src/lib/components/primitives/button/button.component.scss:44:2:
+ 44 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:9:8:
+ 9 │ @import "styles/colors.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:10:8:
+ 10 │ @import "styles/global.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:11:8:
+ 11 │ @import "styles/responsive.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:12:8:
+ 12 │ @import "styles/rounded.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:13:8:
+ 13 │ @import "styles/typography.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] 11 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ null
+
+
+▲ [WARNING] bundle initial exceeded maximum budget. Budget 500.00 kB was not met by 960.04 kB with a total of 1.46 MB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-achievements-step/profile-achievements-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 489 bytes with a total of 2.49 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-experience-step/profile-experience-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 407 bytes with a total of 2.41 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/feed-news-modal/feed-news-modal.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.48 kB with a total of 3.48 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/feed/new-project/new-project.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.42 kB with a total of 6.42 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.71 kB with a total of 5.71 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/feed-news-preview/feed-news-preview.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 7.66 kB with a total of 9.66 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.42 kB with a total of 3.42 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-three/user-type-card/user-type-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.66 kB with a total of 4.66 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 8.95 kB with a total of 10.95 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 305 bytes with a total of 2.31 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.72 kB with a total of 4.72 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/vacancies/detail/info/info.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.49 kB with a total of 6.49 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.31 kB with a total of 7.31 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.52 kB with a total of 5.52 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/avatar-control/avatar-control.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 262 bytes with a total of 2.26 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/project-direction-card/project-direction-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.74 kB with a total of 3.74 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/project-rating.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.06 kB with a total of 5.06 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.02 kB with a total of 7.02 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-two/stage-two.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.88 kB with a total of 6.88 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/office/office.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.10 kB with a total of 4.10 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/invite-card/invite-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 447 bytes with a total of 2.45 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 192 bytes with a total of 2.19 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/members/members-filters/members-filters.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.85 kB with a total of 4.85 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/modal/modal.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 609 bytes with a total of 2.61 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/program-projects-filter/program-projects-filter.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.65 kB with a total of 5.65 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/detail/detail.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 8.91 kB with a total of 10.91 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 11.76 kB with a total of 13.76 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.91 kB with a total of 3.91 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/detail/course-detail.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.81 kB with a total of 5.81 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-one/stage-one.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.88 kB with a total of 5.88 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/vacancy-filter/vacancy-filter.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.21 kB with a total of 6.21 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 6.18 kB with a total of 8.18 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.06 kB with a total of 3.06 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/detail/info/course-module-card/circle-progress-bar/circle-progress-bar.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.46 kB with a total of 4.46 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/chat-window/chat-message/chat-message.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.62 kB with a total of 5.62 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/members/members.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 193 bytes with a total of 2.19 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.66 kB with a total of 6.66 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/list/list.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 519 bytes with a total of 2.52 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.68 kB with a total of 7.68 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-education-step/profile-education-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 407 bytes with a total of 2.41 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.42 kB with a total of 4.42 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 584 bytes with a total of 2.58 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.18 kB with a total of 7.18 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/message-input/message-input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.93 kB with a total of 6.93 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 138 bytes with a total of 2.14 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.93 kB with a total of 3.93 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/collaborator-card/collaborator-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 447 bytes with a total of 2.45 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 12.32 kB with a total of 14.32 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/lesson.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.67 kB with a total of 5.67 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.25 kB with a total of 6.25 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 318 bytes with a total of 2.32 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.07 kB with a total of 3.07 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/courses.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.46 kB with a total of 4.46 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.39 kB with a total of 7.39 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/search/search.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.14 kB with a total of 3.14 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.98 kB with a total of 4.98 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/tag/tag.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.52 kB with a total of 3.52 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/detail/info/info.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.55 kB with a total of 5.55 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/news-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.23 kB with a total of 7.23 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/main/main.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.66 kB with a total of 6.66 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/tooltip/tooltip.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.19 kB with a total of 6.19 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/members/member-statistics-card/member-statistics-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 63 bytes with a total of 2.06 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/edit.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 7.86 kB with a total of 9.86 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.64 kB with a total of 3.64 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/project-invite/project-invite-dialog.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 9.88 kB with a total of 11.88 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-skills-step/profile-skills-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 666 bytes with a total of 2.67 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/complete/complete.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.66 kB with a total of 4.66 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.84 kB with a total of 6.84 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/file-task/file-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.28 kB with a total of 7.28 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.51 kB with a total of 7.51 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-three/stage-three.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.52 kB with a total of 4.52 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 9.31 kB with a total of 11.31 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.57 kB with a total of 7.57 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.78 kB with a total of 4.78 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/select/select.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 6.82 kB with a total of 8.82 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 116 bytes with a total of 2.12 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.71 kB with a total of 4.71 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 7.12 kB with a total of 9.12 kB.
+
+
+▲ [WARNING] projects/ui/src/lib/components/primitives/button/button.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 8.57 kB with a total of 10.57 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/auth/register/register.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.48 kB with a total of 5.48 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 6.40 kB with a total of 8.40 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/auth/login/login.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.93 kB with a total of 5.93 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/carousel/carousel.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.53 kB with a total of 5.53 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/input/input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 9.80 kB with a total of 11.80 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.72 kB with a total of 5.72 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/skills-basket/skills-basket.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.40 kB with a total of 5.40 kB.
+
+
+▲ [WARNING] Module 'dayjs' used by 'projects/social_platform/src/app/api/auth/facades/ui/auth-ui-info.service.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'snakecase-keys' used by 'projects/core/src/lib/interceptors/camelcase.interceptor.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/plugin/customParseFormat' used by 'projects/core/src/lib/services/validation/validation.service.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/plugin/relativeTime' used by 'projects/core/src/lib/services/validation/validation.service.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/plugin/isToday' used by 'projects/core/src/lib/pipes/formatters/dayjs.pipe.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/locale/ru' used by 'projects/core/src/lib/pipes/formatters/dayjs.pipe.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'file-saver' used by 'projects/social_platform/src/app/utils/export-file.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'map-obj' used by 'node_modules/camelcase-keys/index.js' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+Output location: Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\dist\social_platform
diff --git a/docs/desktop-regression/button-tests.log b/docs/desktop-regression/button-tests.log
new file mode 100644
index 000000000..10a6aaed2
--- /dev/null
+++ b/docs/desktop-regression/button-tests.log
@@ -0,0 +1,13 @@
+
+> procollab@0.0.0 test:ci
+> vitest run projects/ui/src/lib/components/primitives/button/button-states.spec.ts
+
+
+ RUN v3.2.6 Z:/Документы/PROCOLLAB-dev/procollab-dev-platform-responsive
+
+ ✓ projects/ui/src/lib/components/primitives/button/button-states.spec.ts (2 tests) 166ms
+
+ Test Files 1 passed (1)
+ Tests 2 passed (2)
+ Start at 15:29:06
+ Duration 7.43s (transform 4.20s, setup 3.33s, collect 1.69s, tests 166ms, environment 1.54s, prepare 1.81s)
diff --git a/docs/desktop-regression/capture-loading.cjs b/docs/desktop-regression/capture-loading.cjs
new file mode 100644
index 000000000..1d7821cc6
--- /dev/null
+++ b/docs/desktop-regression/capture-loading.cjs
@@ -0,0 +1,71 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch } = require("../responsive/browser-harness.cjs");
+require("../mobile-polish/fixtures.cjs");
+const phase = process.argv[2],
+ baseUrl = process.argv[3];
+(async () => {
+ const directory = path.join(__dirname, "screenshots", phase);
+ fs.mkdirSync(directory, { recursive: true });
+ const rows = [];
+ for (const width of [1440, 1920]) {
+ const h = await launch(width, { baseUrl });
+ let release;
+ const pending = new Promise(resolve => {
+ release = resolve;
+ });
+ try {
+ await h.page.goto(baseUrl + "/office/feed");
+ await h.page.waitForLoadState("networkidle");
+ await h.page.evaluate(() => {
+ history.pushState({}, "", "/office/courses/1/lesson/1");
+ dispatchEvent(new PopStateEvent("popstate"));
+ });
+ await h.page.locator("app-write-task textarea").fill("Ответ для финальной проверки UI Kit");
+ await h.page.waitForLoadState("networkidle");
+ await h.page.evaluate(() => {
+ for (const img of document.images) img.loading = "eager";
+ });
+ await h.page.waitForLoadState("networkidle");
+ await h.page.evaluate(() => document.fonts.ready);
+ await h.page.waitForFunction(() => [...document.images].every(img => img.complete));
+ await h.page.addStyleTag({
+ content:
+ "*,*::before,*::after{animation:none!important;transition:none!important;caret-color:transparent!important;}",
+ });
+ await h.context.route("**/courses/tasks/1/answer/", async route => {
+ await pending;
+ await route.fulfill({ json: {} });
+ });
+ await h.page.getByRole("button", { name: "завершить урок", exact: true }).click();
+ await h.page.locator("app-button app-loader").waitFor();
+ if (phase === "desktop-after") {
+ const action = h.page.getByRole("button", { name: "завершить урок", exact: true });
+ assert.equal(await action.isDisabled(), true);
+ assert.equal(await action.getAttribute("aria-busy"), "true");
+ }
+ // Avoid incidental hover; compare the loading presentation itself.
+ await h.page.mouse.move(0, 0);
+ assert.deepEqual(h.errors, []);
+ await h.page.screenshot({
+ path: path.join(directory, `loading-action-${width}.png`),
+ fullPage: true,
+ });
+ rows.push({ name: "loading-action", width, passed: true });
+ console.log(`${phase}: loading-action ${width}`);
+ } finally {
+ release();
+ await h.browser.close();
+ }
+ }
+ fs.writeFileSync(
+ path.join(__dirname, phase + "-loading.json"),
+ JSON.stringify(rows, null, 2) + "\n",
+ );
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/desktop-regression/capture-states.cjs b/docs/desktop-regression/capture-states.cjs
new file mode 100644
index 000000000..929faffc9
--- /dev/null
+++ b/docs/desktop-regression/capture-states.cjs
@@ -0,0 +1,81 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch } = require("../responsive/browser-harness.cjs");
+require("../mobile-polish/fixtures.cjs");
+const phase = process.argv[2],
+ baseUrl = process.argv[3];
+const screens = [
+ [
+ "empty-feed",
+ "/office/feed",
+ /\/feed\/$/,
+ {
+ count: 0,
+ results: [],
+ counts: { all: 0, project: 0, vacancy: 0, news: 0, partnerprogram: 0, education: 0 },
+ },
+ ".page__feed--no-items",
+ ],
+ [
+ "empty-vacancies",
+ "/office/vacancies/all",
+ /\/vacancies\/$/,
+ { count: 0, results: [] },
+ ".page__vacancies--no-items",
+ ],
+ ["empty-courses", "/office/courses/all", /\/courses\/$/, [], "app-list .courses"],
+];
+(async () => {
+ const directory = path.join(__dirname, "screenshots", phase);
+ fs.mkdirSync(directory, { recursive: true });
+ const rows = [];
+ for (const width of [1440, 1920])
+ for (const [name, route, endpoint, response, selector] of screens) {
+ const h = await launch(width, { baseUrl });
+ try {
+ await h.context.route(
+ url => endpoint.test(url.pathname),
+ async request => {
+ await request.fulfill({ json: response });
+ },
+ );
+ await h.page.goto(baseUrl + "/office/feed");
+ await h.page.waitForLoadState("networkidle");
+ if (route !== "/office/feed")
+ await h.page.evaluate(route => {
+ history.pushState({}, "", route);
+ dispatchEvent(new PopStateEvent("popstate"));
+ }, route);
+ await h.page.locator(selector).first().waitFor({ state: "attached" });
+ await h.page.waitForLoadState("networkidle");
+ await h.page.evaluate(() => {
+ for (const img of document.images) img.loading = "eager";
+ });
+ await h.page.evaluate(() => document.fonts.ready);
+ await h.page.waitForFunction(() => [...document.images].every(img => img.complete));
+ await h.page.addStyleTag({
+ content:
+ "*,*::before,*::after{animation:none!important;transition:none!important;caret-color:transparent!important;}",
+ });
+ assert.deepEqual(h.errors, []);
+ await h.page.screenshot({
+ path: path.join(directory, `${name}-${width}.png`),
+ fullPage: true,
+ });
+ rows.push({ name, width, passed: true });
+ console.log(`${phase}: ${name} ${width}`);
+ } finally {
+ await h.browser.close();
+ }
+ }
+ fs.writeFileSync(
+ path.join(__dirname, `${phase}-states.json`),
+ JSON.stringify(rows, null, 2) + "\n",
+ );
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/desktop-regression/capture.cjs b/docs/desktop-regression/capture.cjs
new file mode 100644
index 000000000..65dfde86f
--- /dev/null
+++ b/docs/desktop-regression/capture.cjs
@@ -0,0 +1,116 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch, measure } = require("../responsive/browser-harness.cjs");
+require("../mobile-polish/fixtures.cjs");
+const phase = process.argv[2];
+const baseUrl = process.argv[3];
+const widths = (process.argv[4] || "1440,1920").split(",").map(Number);
+const editing = process.argv[5] === "edit";
+const screens = editing
+ ? [
+ ["profile-edit", "/office/profile/edit?editingStep=main", "app-profile-main-step"],
+ [
+ "project-edit",
+ "/office/projects/1/edit?editingStep=main&programLinkId=1",
+ "app-project-main-step",
+ ],
+ ]
+ : [
+ ["feed", "/office/feed", "app-open-vacancy"],
+ ["projects", "/office/projects/dashboard", "app-info-card"],
+ ["my-projects", "/office/projects/my", "app-info-card"],
+ ["members", "/office/members", "app-member-card"],
+ ["programs", "/office/program/all", "app-program-card"],
+ ["program", "/office/program/1", "app-program-role-widget"],
+ ["profile", "/office/profile/1", "app-profile-left-side"],
+ ["project", "/office/projects/1", "app-projects-left-side"],
+ ["vacancies", "/office/vacancies/all", "app-project-vacancy-card"],
+ ["vacancy", "/office/vacancies/1", "app-vacancies-detail"],
+ ["courses", "/office/courses/all", "app-course"],
+ ["course", "/office/courses/1", "app-course-detail"],
+ ];
+(async () => {
+ const directory = path.join(__dirname, "screenshots", phase);
+ fs.mkdirSync(directory, { recursive: true });
+ const rows = [];
+ for (const width of widths) {
+ const h = await launch(width, { baseUrl, isMobile: width < 750, hasTouch: width < 750 });
+ try {
+ // Fixed clock, no animations, no screenshot masks or omitted page sections.
+ await h.context.addInitScript(() => {
+ const NativeDate = Date;
+ class FixedDate extends NativeDate {
+ constructor(...args) {
+ super(...(args.length ? args : [1791288000000]));
+ }
+ static now() {
+ return 1791288000000;
+ }
+ }
+ window.Date = FixedDate;
+ });
+ await h.page.goto(baseUrl + "/office/feed");
+ await h.page.waitForLoadState("networkidle");
+ for (const [name, route, selector] of screens) {
+ h.errors.length = 0;
+ if (name === "feed") await h.page.goto(baseUrl + route);
+ else
+ await h.page.evaluate(route => {
+ history.pushState({}, "", route);
+ dispatchEvent(new PopStateEvent("popstate"));
+ }, route);
+ await h.page.waitForURL(baseUrl + route);
+ await h.page.waitForLoadState("networkidle");
+ await h.page
+ .locator(selector)
+ .first()
+ .waitFor({ state: "attached" })
+ .catch(async error => {
+ console.error(
+ JSON.stringify(
+ {
+ url: h.page.url(),
+ text: await h.page.locator("body").innerText(),
+ errors: h.errors,
+ requests: h.requests,
+ },
+ null,
+ 2,
+ ),
+ );
+ throw error;
+ });
+ await h.page.evaluate(() => {
+ for (const img of document.images) img.loading = "eager";
+ });
+ await h.page.waitForLoadState("networkidle");
+ await h.page.evaluate(() => document.fonts.ready);
+ await h.page.waitForFunction(() => [...document.images].every(img => img.complete));
+ await h.page.addStyleTag({
+ content:
+ "*, *::before, *::after { animation: none !important; transition: none !important; caret-color: transparent !important; }",
+ });
+ const measurement = await measure(h.page);
+ assert.deepEqual(h.errors, [], `${phase} ${name} ${width}`);
+ await h.page.screenshot({
+ path: path.join(directory, `${name}-${width}.png`),
+ fullPage: true,
+ });
+ rows.push({ name, width, ...measurement });
+ console.log(`${phase}: ${name} ${width}`);
+ }
+ } finally {
+ await h.browser.close();
+ }
+ }
+ fs.writeFileSync(
+ path.join(__dirname, `${phase}${editing ? "-edit" : ""}.json`),
+ JSON.stringify(rows, null, 2) + "\n",
+ );
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/desktop-regression/compare.py b/docs/desktop-regression/compare.py
new file mode 100644
index 000000000..d297180f8
--- /dev/null
+++ b/docs/desktop-regression/compare.py
@@ -0,0 +1,46 @@
+"""Compare full-page PNGs without masks; fail the visual regression gate."""
+import json
+import sys
+from pathlib import Path
+
+import numpy as np
+from PIL import Image
+
+root = Path(__file__).parent
+before, after = sys.argv[1:3]
+output = root / "screenshots" / f"diff-{after}"
+output.mkdir(parents=True, exist_ok=True)
+rows = []
+for file in sorted((root / "screenshots" / before).glob("*.png")):
+ a = Image.open(file).convert("RGB")
+ b = Image.open(root / "screenshots" / after / file.name).convert("RGB")
+ same_size = a.size == b.size
+ w, h = max(a.width, b.width), max(a.height, b.height)
+ padded = []
+ for img in (a, b):
+ canvas = Image.new("RGB", (w, h), "white")
+ canvas.paste(img)
+ padded.append(np.asarray(canvas).astype(np.int16))
+ delta = np.max(np.abs(padded[0] - padded[1]), axis=2)
+ mask = delta > 8
+ count = int(np.count_nonzero(mask))
+ percent = count / (w * h) * 100
+ ys, xs = np.where(mask)
+ bbox = [int(xs.min()), int(ys.min()), int(xs.max()), int(ys.max())] if count else None
+ exact_count = int(np.count_nonzero(delta))
+ passed = same_size and exact_count == 0
+ rows.append({"screen": file.stem, "beforeSize": a.size, "afterSize": b.size,
+ "changedPixels": count, "changedPercent": round(percent, 6),
+ "exactChangedPixels": exact_count,
+ "maxChannelDelta": int(delta.max()),
+ "bbox": bbox, "passed": passed})
+ if count or not same_size:
+ overlay = (padded[1] * 0.4 + 255 * 0.6).astype(np.uint8)
+ overlay[mask] = [240, 40, 100]
+ Image.fromarray(overlay).save(output / file.name)
+ else:
+ (output / file.name).unlink(missing_ok=True)
+ print(f"{'PASS' if passed else 'FAIL'} {file.stem}: exact={exact_count}px; delta>8={percent:.4f}% {a.size} -> {b.size} bbox={bbox}")
+(root / f"comparison-{after}.json").write_text(json.dumps(rows, indent=2) + "\n", encoding="utf-8")
+if "--check" in sys.argv and (not rows or any(not r["passed"] for r in rows)):
+ sys.exit(1)
diff --git a/docs/desktop-regression/comparison-data.js b/docs/desktop-regression/comparison-data.js
new file mode 100644
index 000000000..188145608
--- /dev/null
+++ b/docs/desktop-regression/comparison-data.js
@@ -0,0 +1,1332 @@
+const pixelComparisons = {
+ "desktop": [
+ {
+ "screen": "course-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "course-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-courses-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-courses-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-feed-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-feed-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-vacancies-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-vacancies-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "loading-action-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "loading-action-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-1440",
+ "beforeSize": [
+ 1440,
+ 844
+ ],
+ "afterSize": [
+ 1440,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-1920",
+ "beforeSize": [
+ 1920,
+ 844
+ ],
+ "afterSize": [
+ 1920,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ }
+ ],
+ "mobile": [
+ {
+ "screen": "course-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "course-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "course-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-320",
+ "beforeSize": [
+ 320,
+ 844
+ ],
+ "afterSize": [
+ 320,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-390",
+ "beforeSize": [
+ 390,
+ 844
+ ],
+ "afterSize": [
+ 390,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-768",
+ "beforeSize": [
+ 768,
+ 844
+ ],
+ "afterSize": [
+ 768,
+ 844
+ ],
+ "changedPixels": 0,
+ "changedPercent": 0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ }
+ ]
+};
diff --git a/docs/desktop-regression/comparison-desktop-after.json b/docs/desktop-regression/comparison-desktop-after.json
new file mode 100644
index 000000000..9a0a12922
--- /dev/null
+++ b/docs/desktop-regression/comparison-desktop-after.json
@@ -0,0 +1,398 @@
+[
+ {
+ "screen": "course-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "course-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-courses-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-courses-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-feed-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-feed-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-vacancies-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-vacancies-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "loading-action-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "loading-action-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/comparison-desktop-repeat.json b/docs/desktop-regression/comparison-desktop-repeat.json
new file mode 100644
index 000000000..9a0a12922
--- /dev/null
+++ b/docs/desktop-regression/comparison-desktop-repeat.json
@@ -0,0 +1,398 @@
+[
+ {
+ "screen": "course-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "course-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-courses-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-courses-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-feed-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-feed-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-vacancies-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "empty-vacancies-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "loading-action-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "loading-action-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-1440",
+ "beforeSize": [1440, 844],
+ "afterSize": [1440, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-1920",
+ "beforeSize": [1920, 844],
+ "afterSize": [1920, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/comparison-mobile-after.json b/docs/desktop-regression/comparison-mobile-after.json
new file mode 100644
index 000000000..d3c305d21
--- /dev/null
+++ b/docs/desktop-regression/comparison-mobile-after.json
@@ -0,0 +1,464 @@
+[
+ {
+ "screen": "course-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "course-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "course-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "courses-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "feed-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "members-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "my-projects-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "profile-edit-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "program-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "programs-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "project-edit-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "projects-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancies-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-320",
+ "beforeSize": [320, 844],
+ "afterSize": [320, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-390",
+ "beforeSize": [390, 844],
+ "afterSize": [390, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ },
+ {
+ "screen": "vacancy-768",
+ "beforeSize": [768, 844],
+ "afterSize": [768, 844],
+ "changedPixels": 0,
+ "changedPercent": 0.0,
+ "exactChangedPixels": 0,
+ "maxChannelDelta": 0,
+ "bbox": null,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/comparison.html b/docs/desktop-regression/comparison.html
new file mode 100644
index 000000000..854ecd74a
--- /dev/null
+++ b/docs/desktop-regression/comparison.html
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+ PROCOLLAB — visual regression
+
+
+
+
+
+
+ Эталон
+
+
![Эталон]()
![Исправление для наложения]()
+
+
+
+ После исправления
+
+
+
+
+
+
+
diff --git a/docs/desktop-regression/desktop-after-edit.json b/docs/desktop-regression/desktop-after-edit.json
new file mode 100644
index 000000000..565a21397
--- /dev/null
+++ b/docs/desktop-regression/desktop-after-edit.json
@@ -0,0 +1,212 @@
+[
+ {
+ "name": "profile-edit",
+ "width": 1440,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактирование профиля\ncохранить\n\nосновные данные\n\nобразование\n\nработа\n\nдостижения\n\nнавы"
+ },
+ {
+ "name": "project-edit",
+ "width": 1440,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактировать проект\nудалить проект\nсохранить черновик\nотправить заявку\n\nосновные данные"
+ },
+ {
+ "name": "profile-edit",
+ "width": 1920,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактирование профиля\ncохранить\n\nосновные данные\n\nобразование\n\nработа\n\nдостижения\n\nнавы"
+ },
+ {
+ "name": "project-edit",
+ "width": 1920,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактировать проект\nудалить проект\nсохранить черновик\nотправить заявку\n\nосновные данные"
+ }
+]
diff --git a/docs/desktop-regression/desktop-after-loading.json b/docs/desktop-regression/desktop-after-loading.json
new file mode 100644
index 000000000..97d812e6c
--- /dev/null
+++ b/docs/desktop-regression/desktop-after-loading.json
@@ -0,0 +1,12 @@
+[
+ {
+ "name": "loading-action",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "loading-action",
+ "width": 1920,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/desktop-after-states.json b/docs/desktop-regression/desktop-after-states.json
new file mode 100644
index 000000000..02e2050be
--- /dev/null
+++ b/docs/desktop-regression/desktop-after-states.json
@@ -0,0 +1,32 @@
+[
+ {
+ "name": "empty-feed",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-vacancies",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-courses",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-feed",
+ "width": 1920,
+ "passed": true
+ },
+ {
+ "name": "empty-vacancies",
+ "width": 1920,
+ "passed": true
+ },
+ {
+ "name": "empty-courses",
+ "width": 1920,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/desktop-after.json b/docs/desktop-regression/desktop-after.json
new file mode 100644
index 000000000..1d46c5d44
--- /dev/null
+++ b/docs/desktop-regression/desktop-after.json
@@ -0,0 +1,1168 @@
+[
+ {
+ "name": "feed",
+ "width": 1440,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр"
+ },
+ {
+ "name": "projects",
+ "width": 1440,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселер"
+ },
+ {
+ "name": "my-projects",
+ "width": 1440,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к програм"
+ },
+ {
+ "name": "members",
+ "width": 1440,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело"
+ },
+ {
+ "name": "programs",
+ "width": 1440,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n"
+ },
+ {
+ "name": "program",
+ "width": 1440,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nоценка проектов\nаналитика\nпроекты-участники\nучастники\nаналитика\nорганизатор\nУчастники\n1\n"
+ },
+ {
+ "name": "profile",
+ "width": 1440,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26"
+ },
+ {
+ "name": "project",
+ "width": 1440,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе"
+ },
+ {
+ "name": "vacancies",
+ "width": 1440,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезП"
+ },
+ {
+ "name": "vacancy",
+ "width": 1440,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинно"
+ },
+ {
+ "name": "courses",
+ "width": 1440,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-button",
+ "app-soon-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-soon-card",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНа"
+ },
+ {
+ "name": "course",
+ "width": 1440,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро"
+ },
+ {
+ "name": "feed",
+ "width": 1920,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр"
+ },
+ {
+ "name": "projects",
+ "width": 1920,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселер"
+ },
+ {
+ "name": "my-projects",
+ "width": 1920,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к програм"
+ },
+ {
+ "name": "members",
+ "width": 1920,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело"
+ },
+ {
+ "name": "programs",
+ "width": 1920,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n"
+ },
+ {
+ "name": "program",
+ "width": 1920,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nоценка проектов\nаналитика\nпроекты-участники\nучастники\nаналитика\nорганизатор\nУчастники\n1\n"
+ },
+ {
+ "name": "profile",
+ "width": 1920,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26"
+ },
+ {
+ "name": "project",
+ "width": 1920,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе"
+ },
+ {
+ "name": "vacancies",
+ "width": 1920,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезП"
+ },
+ {
+ "name": "vacancy",
+ "width": 1920,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинно"
+ },
+ {
+ "name": "courses",
+ "width": 1920,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-button",
+ "app-soon-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-soon-card",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНа"
+ },
+ {
+ "name": "course",
+ "width": 1920,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро"
+ }
+]
diff --git a/docs/desktop-regression/desktop-before-edit.json b/docs/desktop-regression/desktop-before-edit.json
new file mode 100644
index 000000000..565a21397
--- /dev/null
+++ b/docs/desktop-regression/desktop-before-edit.json
@@ -0,0 +1,212 @@
+[
+ {
+ "name": "profile-edit",
+ "width": 1440,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактирование профиля\ncохранить\n\nосновные данные\n\nобразование\n\nработа\n\nдостижения\n\nнавы"
+ },
+ {
+ "name": "project-edit",
+ "width": 1440,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактировать проект\nудалить проект\nсохранить черновик\nотправить заявку\n\nосновные данные"
+ },
+ {
+ "name": "profile-edit",
+ "width": 1920,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактирование профиля\ncохранить\n\nосновные данные\n\nобразование\n\nработа\n\nдостижения\n\nнавы"
+ },
+ {
+ "name": "project-edit",
+ "width": 1920,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактировать проект\nудалить проект\nсохранить черновик\nотправить заявку\n\nосновные данные"
+ }
+]
diff --git a/docs/desktop-regression/desktop-before-loading.json b/docs/desktop-regression/desktop-before-loading.json
new file mode 100644
index 000000000..97d812e6c
--- /dev/null
+++ b/docs/desktop-regression/desktop-before-loading.json
@@ -0,0 +1,12 @@
+[
+ {
+ "name": "loading-action",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "loading-action",
+ "width": 1920,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/desktop-before-states.json b/docs/desktop-regression/desktop-before-states.json
new file mode 100644
index 000000000..02e2050be
--- /dev/null
+++ b/docs/desktop-regression/desktop-before-states.json
@@ -0,0 +1,32 @@
+[
+ {
+ "name": "empty-feed",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-vacancies",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-courses",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-feed",
+ "width": 1920,
+ "passed": true
+ },
+ {
+ "name": "empty-vacancies",
+ "width": 1920,
+ "passed": true
+ },
+ {
+ "name": "empty-courses",
+ "width": 1920,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/desktop-before.json b/docs/desktop-regression/desktop-before.json
new file mode 100644
index 000000000..5a4c70444
--- /dev/null
+++ b/docs/desktop-regression/desktop-before.json
@@ -0,0 +1,1152 @@
+[
+ {
+ "name": "feed",
+ "width": 1440,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр"
+ },
+ {
+ "name": "projects",
+ "width": 1440,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселер"
+ },
+ {
+ "name": "my-projects",
+ "width": 1440,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к програм"
+ },
+ {
+ "name": "members",
+ "width": 1440,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело"
+ },
+ {
+ "name": "programs",
+ "width": 1440,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n"
+ },
+ {
+ "name": "program",
+ "width": 1440,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nоценка проектов\nаналитика\nпроекты-участники\nучастники\nаналитика\nорганизатор\nУчастники\n1\n"
+ },
+ {
+ "name": "profile",
+ "width": 1440,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26"
+ },
+ {
+ "name": "project",
+ "width": 1440,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе"
+ },
+ {
+ "name": "vacancies",
+ "width": 1440,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезП"
+ },
+ {
+ "name": "vacancy",
+ "width": 1440,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинно"
+ },
+ {
+ "name": "courses",
+ "width": 1440,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-button",
+ "app-soon-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-soon-card",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНа"
+ },
+ {
+ "name": "course",
+ "width": 1440,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро"
+ },
+ {
+ "name": "feed",
+ "width": 1920,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр"
+ },
+ {
+ "name": "projects",
+ "width": 1920,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселер"
+ },
+ {
+ "name": "my-projects",
+ "width": 1920,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к програм"
+ },
+ {
+ "name": "members",
+ "width": 1920,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело"
+ },
+ {
+ "name": "programs",
+ "width": 1920,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n"
+ },
+ {
+ "name": "program",
+ "width": 1920,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nоценка проектов\nаналитика\nпроекты-участники\nучастники\nаналитика\nорганизатор\nУчастники\n1\n"
+ },
+ {
+ "name": "profile",
+ "width": 1920,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26"
+ },
+ {
+ "name": "project",
+ "width": 1920,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе"
+ },
+ {
+ "name": "vacancies",
+ "width": 1920,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезП"
+ },
+ {
+ "name": "vacancy",
+ "width": 1920,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинно"
+ },
+ {
+ "name": "courses",
+ "width": 1920,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-button",
+ "app-soon-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-soon-card",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНа"
+ },
+ {
+ "name": "course",
+ "width": 1920,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро"
+ }
+]
diff --git a/docs/desktop-regression/desktop-repeat-edit.json b/docs/desktop-regression/desktop-repeat-edit.json
new file mode 100644
index 000000000..565a21397
--- /dev/null
+++ b/docs/desktop-regression/desktop-repeat-edit.json
@@ -0,0 +1,212 @@
+[
+ {
+ "name": "profile-edit",
+ "width": 1440,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактирование профиля\ncохранить\n\nосновные данные\n\nобразование\n\nработа\n\nдостижения\n\nнавы"
+ },
+ {
+ "name": "project-edit",
+ "width": 1440,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактировать проект\nудалить проект\nсохранить черновик\nотправить заявку\n\nосновные данные"
+ },
+ {
+ "name": "profile-edit",
+ "width": 1920,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактирование профиля\ncохранить\n\nосновные данные\n\nобразование\n\nработа\n\nдостижения\n\nнавы"
+ },
+ {
+ "name": "project-edit",
+ "width": 1920,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nредактировать проект\nудалить проект\nсохранить черновик\nотправить заявку\n\nосновные данные"
+ }
+]
diff --git a/docs/desktop-regression/desktop-repeat-loading.json b/docs/desktop-regression/desktop-repeat-loading.json
new file mode 100644
index 000000000..97d812e6c
--- /dev/null
+++ b/docs/desktop-regression/desktop-repeat-loading.json
@@ -0,0 +1,12 @@
+[
+ {
+ "name": "loading-action",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "loading-action",
+ "width": 1920,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/desktop-repeat-states.json b/docs/desktop-regression/desktop-repeat-states.json
new file mode 100644
index 000000000..02e2050be
--- /dev/null
+++ b/docs/desktop-regression/desktop-repeat-states.json
@@ -0,0 +1,32 @@
+[
+ {
+ "name": "empty-feed",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-vacancies",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-courses",
+ "width": 1440,
+ "passed": true
+ },
+ {
+ "name": "empty-feed",
+ "width": 1920,
+ "passed": true
+ },
+ {
+ "name": "empty-vacancies",
+ "width": 1920,
+ "passed": true
+ },
+ {
+ "name": "empty-courses",
+ "width": 1920,
+ "passed": true
+ }
+]
diff --git a/docs/desktop-regression/desktop-repeat.json b/docs/desktop-regression/desktop-repeat.json
new file mode 100644
index 000000000..5a4c70444
--- /dev/null
+++ b/docs/desktop-regression/desktop-repeat.json
@@ -0,0 +1,1152 @@
+[
+ {
+ "name": "feed",
+ "width": 1440,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр"
+ },
+ {
+ "name": "projects",
+ "width": 1440,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселер"
+ },
+ {
+ "name": "my-projects",
+ "width": 1440,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к програм"
+ },
+ {
+ "name": "members",
+ "width": 1440,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело"
+ },
+ {
+ "name": "programs",
+ "width": 1440,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n"
+ },
+ {
+ "name": "program",
+ "width": 1440,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nоценка проектов\nаналитика\nпроекты-участники\nучастники\nаналитика\nорганизатор\nУчастники\n1\n"
+ },
+ {
+ "name": "profile",
+ "width": 1440,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26"
+ },
+ {
+ "name": "project",
+ "width": 1440,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе"
+ },
+ {
+ "name": "vacancies",
+ "width": 1440,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезП"
+ },
+ {
+ "name": "vacancy",
+ "width": 1440,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинно"
+ },
+ {
+ "name": "courses",
+ "width": 1440,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-button",
+ "app-soon-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-soon-card",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНа"
+ },
+ {
+ "name": "course",
+ "width": 1440,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро"
+ },
+ {
+ "name": "feed",
+ "width": 1920,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр"
+ },
+ {
+ "name": "projects",
+ "width": 1920,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселер"
+ },
+ {
+ "name": "my-projects",
+ "width": 1920,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-button",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-back",
+ "app-search",
+ "app-bar-new",
+ "app-list",
+ "app-info-card",
+ "app-button",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к програм"
+ },
+ {
+ "name": "members",
+ "width": 1920,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело"
+ },
+ {
+ "name": "programs",
+ "width": 1920,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n"
+ },
+ {
+ "name": "program",
+ "width": 1920,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nоценка проектов\nаналитика\nпроекты-участники\nучастники\nаналитика\nорганизатор\nУчастники\n1\n"
+ },
+ {
+ "name": "profile",
+ "width": 1920,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26"
+ },
+ {
+ "name": "project",
+ "width": 1920,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе"
+ },
+ {
+ "name": "vacancies",
+ "width": 1920,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезП"
+ },
+ {
+ "name": "vacancy",
+ "width": 1920,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинно"
+ },
+ {
+ "name": "courses",
+ "width": 1920,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-button",
+ "app-soon-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-soon-card",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНа"
+ },
+ {
+ "name": "course",
+ "width": 1920,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 1920,
+ "pageWidth": 1905,
+ "bodyWidth": 1905,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-soon-card",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-course-about"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро"
+ }
+]
diff --git a/docs/desktop-regression/eslint.log b/docs/desktop-regression/eslint.log
new file mode 100644
index 000000000..f1179cf5e
--- /dev/null
+++ b/docs/desktop-regression/eslint.log
@@ -0,0 +1,19 @@
+
+> procollab@0.0.0 lint:ts
+> eslint projects/**/*.ts
+
+
+Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\projects\core\src\lib\services\logger\logger.service.ts
+ 47:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+ 61:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+ 73:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+ 85:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+
+Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\projects\social_platform\src\app\domain\chat\chat-message.model.ts
+ 22:3 warning Unused eslint-disable directive (no problems were reported from 'no-use-before-define')
+
+Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\projects\social_platform\src\app\ui\widgets\message-input\message-input.component.ts
+ 176:3 warning Unused eslint-disable directive (no problems were reported from 'no-use-before-define')
+
+✖ 6 problems (0 errors, 6 warnings)
+ 0 errors and 6 warnings potentially fixable with the `--fix` option.
diff --git a/docs/desktop-regression/interactions.cjs b/docs/desktop-regression/interactions.cjs
new file mode 100644
index 000000000..eeea72d14
--- /dev/null
+++ b/docs/desktop-regression/interactions.cjs
@@ -0,0 +1,186 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch, assertViewport } = require("../responsive/browser-harness.cjs");
+const fixtures = require("../mobile-polish/fixtures.cjs");
+const rows = [];
+const directory = path.join(__dirname, "screenshots", "interactions");
+fs.mkdirSync(directory, { recursive: true });
+
+async function goto(h, route, selector) {
+ h.errors.length = 0;
+ await h.page.goto(h.base + route);
+ await h.page.waitForLoadState("networkidle");
+ await h.page.locator(selector).first().waitFor();
+}
+
+async function check(h, name, width, details = {}) {
+ const measurement = await assertViewport(h.page);
+ assert.deepEqual(h.errors, []);
+ const screenshot = `screenshots/interactions/${name}-${width}.png`;
+ await h.page.screenshot({ path: path.join(__dirname, screenshot), fullPage: true });
+ rows.push({ name, width, passed: true, ...details, ...measurement, screenshot });
+ console.log(`${name} ${width}: passed`);
+}
+
+(async () => {
+ for (const width of [320, 390, 768]) {
+ const h = await launch(width, { isMobile: width < 750, hasTouch: width < 750 });
+ h.page.setDefaultTimeout(10000);
+ try {
+ await goto(h, "/office/program/all", "app-program-card");
+ const region = h.page.locator(".card__region").first();
+ assert.equal((await region.textContent()).trim(), "для всей России");
+ assert.ok(await region.evaluate(el => el.scrollWidth <= el.clientWidth + 1));
+ await h.page.getByRole("button", { name: "Открыть меню", exact: true }).click();
+ assert.equal(await h.page.getByRole("button", { name: "Выйти", exact: true }).count(), 1);
+ await h.page.locator("#mobile-navigation a[routerLink=feed]").click();
+ await h.page.locator("app-open-vacancy").waitFor();
+ await h.page.waitForLoadState("networkidle");
+ assert.equal((await h.page.locator(".nav-bar__title").textContent()).trim(), "Новости");
+ const title = await h.page.locator(".nav-bar__title").boundingBox();
+ const header = await h.page.locator(".office__top").boundingBox();
+ assert.ok(Math.abs(title.x + title.width / 2 - header.x - header.width / 2) <= 1);
+ assert.equal(
+ await h.page.locator(".office__top").evaluate(el => getComputedStyle(el).backgroundImage),
+ "none",
+ );
+ for (const selector of [
+ ".nav-bar__toggle",
+ "button.control-panel__action",
+ ".control-panel__profile .user",
+ ]) {
+ const box = await h.page.locator(selector).boundingBox();
+ assert.ok(box.width >= 44 && box.height >= 44, selector + " target");
+ }
+ assert.equal(await h.page.locator("app-feed-filter .filter__option").count(), 6);
+ assert.equal(await h.page.locator("app-feed-filter .select").count(), 0);
+ const notifications = h.page.getByRole("button", { name: "Уведомления", exact: true });
+ await notifications.focus();
+ await h.page.keyboard.press("Enter");
+ await h.page.locator(".control-panel__notifications").waitFor();
+ assert.equal(await notifications.getAttribute("aria-expanded"), "true");
+ await h.page.locator("app-open-vacancy h3").click();
+ await h.page.locator(".control-panel__notifications").waitFor({ state: "detached" });
+ const noOverlap = await h.page
+ .locator("app-feed-filter .filter__option")
+ .evaluateAll(options =>
+ options.every(option => {
+ const icon = option.querySelector(".filter__option--icon").getBoundingClientRect();
+ const label = option.querySelector(".filter__title").getBoundingClientRect();
+ const count = option.querySelector(".filter__count").getBoundingClientRect();
+ return (
+ icon.right <= label.left && (label.bottom <= count.top || label.right <= count.left)
+ );
+ }),
+ );
+ assert.ok(noOverlap);
+ const toggle = h.page.locator("app-open-vacancy .skills__toggle");
+ await toggle.click();
+ await h.page.locator("app-open-vacancy app-tag").nth(3).waitFor();
+ assert.equal(await toggle.getAttribute("aria-expanded"), "true");
+ assert.equal(await h.page.locator("app-open-vacancy app-tag").count(), 4);
+ const skillVisible = await h.page.locator("app-open-vacancy app-tag").evaluateAll(tags =>
+ tags.every(tag => {
+ const el = tag.querySelector("p") || tag;
+ const s = getComputedStyle(el);
+ return s.textOverflow !== "ellipsis" && el.scrollWidth <= el.clientWidth + 1;
+ }),
+ );
+ assert.ok(skillVisible);
+ const category = h.page.locator(".filter__option").filter({ hasText: "свежие вакансии" });
+ await category.click();
+ await h.page.waitForURL(/includes=vacancy/);
+ await h.page.waitForLoadState("networkidle");
+ assert.equal(await category.getAttribute("aria-pressed"), "true");
+ assert.ok(h.requests.some(r => /\/feed\/$/.test(r.path) && /type=vacancy/.test(r.query)));
+ const disabled = h.page.getByRole("button", { name: /образование/ });
+ assert.equal(await disabled.isDisabled(), true);
+ const url = h.page.url();
+ await disabled.evaluate(el => el.click());
+ assert.equal(h.page.url(), url);
+ await check(h, "navigation-feed-skills", width);
+
+ await goto(h, "/office/projects/dashboard", "app-info-card");
+ const activity = await h.page.locator("app-project-activity-card").boundingBox();
+ const list = await h.page.locator(".page__outlet").boundingBox();
+ const parent = await h.page.locator(".page__info").boundingBox();
+ assert.ok(activity.y + activity.height <= list.y + 1);
+ assert.ok(Math.abs(activity.width - parent.width) <= 1);
+ assert.equal(
+ await h.page
+ .locator(".activity__metrics")
+ .evaluate(el => getComputedStyle(el).gridTemplateColumns.split(" ").length),
+ 2,
+ );
+ const card = await h.page.locator("app-info-card .card__body").first().boundingBox();
+ assert.ok(card.width <= 261 && card.width < parent.width);
+ await check(h, "projects-activity", width);
+
+ await goto(h, "/office/members", "app-member-card");
+ const member = await h.page.locator("app-member-card .member-card").first().boundingBox();
+ assert.ok(member.width <= 261);
+ await check(h, "members", width);
+
+ for (const [name, route] of [
+ ["profile", "/office/profile/1"],
+ ["project", "/office/projects/1"],
+ ["program", "/office/program/1"],
+ ]) {
+ await goto(h, route, ".info__actions app-button");
+ const actions = await h.page.locator(".info__actions").boundingBox();
+ const children = await h.page
+ .locator(
+ ".info__actions > a, .info__actions > app-button, .info__actions > .info__unavailable",
+ )
+ .all();
+ for (const child of children) {
+ if (!(await child.isVisible())) continue;
+ const box = await child.boundingBox();
+ assert.ok(Math.abs(box.width - (actions.width - 12) / 2) <= 1, `${name} action column`);
+ const button = child.locator("button").first();
+ const buttonBox = await button.boundingBox();
+ assert.ok(
+ buttonBox.height >= 44 && Math.abs(buttonBox.width - box.width) <= 1,
+ `${name} button target`,
+ );
+ }
+ assert.equal(await h.page.locator(".info__divider:visible").count(), 0);
+ assert.ok((await h.page.locator(".info__page-header").textContent()).trim().length > 0);
+ if (name === "project") {
+ const metadata = await h.page.locator("app-projects-left-side").boundingBox();
+ assert.ok(metadata.width > actions.width - 2, "project metadata full width");
+ }
+ if (name === "program") {
+ const contacts = h.page.getByRole("button", { name: "Контакты", exact: true });
+ assert.equal(await contacts.count(), 1);
+ assert.equal(await contacts.isDisabled(), true);
+ }
+ await check(h, `${name}-actions`, width);
+ }
+ await h.page.getByRole("link", { name: "Мой профиль", exact: true }).click();
+ await h.page.waitForURL(/\/office\/profile\/1$/);
+ await h.page.waitForLoadState("networkidle");
+ assert.equal((await h.page.locator(".nav-bar__title").textContent()).trim(), "Профиль");
+ await h.page.getByRole("button", { name: "Открыть меню", exact: true }).click();
+ await h.page.locator("#mobile-navigation").waitFor();
+ await h.page.waitForFunction(() => !!document.activeElement?.closest("#mobile-navigation"));
+ await h.page.keyboard.press("Escape");
+ await h.page.locator("#mobile-navigation").waitFor({ state: "detached" });
+ assert.equal(await h.page.locator("#mobile-navigation").count(), 0);
+ assert.equal(
+ await h.page.locator(".nav-bar__toggle").evaluate(el => document.activeElement === el),
+ true,
+ );
+ } finally {
+ await h.browser.close();
+ }
+ }
+ fs.writeFileSync(path.join(__dirname, "interactions.json"), JSON.stringify(rows, null, 2) + "\n");
+ console.log(`${rows.length} interaction screens passed`);
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/desktop-regression/interactions.json b/docs/desktop-regression/interactions.json
new file mode 100644
index 000000000..0ab753dd2
--- /dev/null
+++ b/docs/desktop-regression/interactions.json
@@ -0,0 +1,917 @@
+[
+ {
+ "name": "navigation-feed-skills",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "?includes=vacancy",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "screenshot": "screenshots/interactions/navigation-feed-skills-320.png"
+ },
+ {
+ "name": "projects-activity",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "screenshot": "screenshots/interactions/projects-activity-320.png"
+ },
+ {
+ "name": "members",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "screenshot": "screenshots/interactions/members-320.png"
+ },
+ {
+ "name": "profile-actions",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "screenshot": "screenshots/interactions/profile-actions-320.png"
+ },
+ {
+ "name": "project-actions",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "screenshot": "screenshots/interactions/project-actions-320.png"
+ },
+ {
+ "name": "program-actions",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "screenshot": "screenshots/interactions/program-actions-320.png"
+ },
+ {
+ "name": "navigation-feed-skills",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "?includes=vacancy",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "screenshot": "screenshots/interactions/navigation-feed-skills-390.png"
+ },
+ {
+ "name": "projects-activity",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "screenshot": "screenshots/interactions/projects-activity-390.png"
+ },
+ {
+ "name": "members",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "screenshot": "screenshots/interactions/members-390.png"
+ },
+ {
+ "name": "profile-actions",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "screenshot": "screenshots/interactions/profile-actions-390.png"
+ },
+ {
+ "name": "project-actions",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "screenshot": "screenshots/interactions/project-actions-390.png"
+ },
+ {
+ "name": "program-actions",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "screenshot": "screenshots/interactions/program-actions-390.png"
+ },
+ {
+ "name": "navigation-feed-skills",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "?includes=vacancy",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "screenshot": "screenshots/interactions/navigation-feed-skills-768.png"
+ },
+ {
+ "name": "projects-activity",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "screenshot": "screenshots/interactions/projects-activity-768.png"
+ },
+ {
+ "name": "members",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "screenshot": "screenshots/interactions/members-768.png"
+ },
+ {
+ "name": "profile-actions",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "screenshot": "screenshots/interactions/profile-actions-768.png"
+ },
+ {
+ "name": "project-actions",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "screenshot": "screenshots/interactions/project-actions-768.png"
+ },
+ {
+ "name": "program-actions",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "screenshot": "screenshots/interactions/program-actions-768.png"
+ }
+]
diff --git a/docs/desktop-regression/mobile-after-edit.json b/docs/desktop-regression/mobile-after-edit.json
new file mode 100644
index 000000000..79ec36bc7
--- /dev/null
+++ b/docs/desktop-regression/mobile-after-edit.json
@@ -0,0 +1,341 @@
+[
+ {
+ "name": "profile-edit",
+ "width": 320,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон"
+ },
+ {
+ "name": "project-edit",
+ "width": 320,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "Редактирование проекта\nудалить проект\nсохранить черновик\nотправить заявку\nосновные данные\nпартнеры и ресурсы\nдостижения\nвакансии\nкоманда\nданные для конкурсов\nлоготип\nпрезентация\n\nПрезентации формата .PDF\nили .PPTX весом до 50МБ\n\nобложка\n\nСтандартная обложка\n\nЗагрузить файл\n1\nназвание\n\n17 / 256\n\nреги"
+ },
+ {
+ "name": "profile-edit",
+ "width": 390,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон"
+ },
+ {
+ "name": "project-edit",
+ "width": 390,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "Редактирование проекта\nудалить проект\nсохранить черновик\nотправить заявку\nосновные данные\nпартнеры и ресурсы\nдостижения\nвакансии\nкоманда\nданные для конкурсов\nлоготип\nпрезентация\n\nПрезентации формата .PDF\nили .PPTX весом до 50МБ\n\nобложка\n\nСтандартная обложка\n\nЗагрузить файл\n1\nназвание\n\n17 / 256\n\nреги"
+ },
+ {
+ "name": "profile-edit",
+ "width": 768,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон"
+ },
+ {
+ "name": "project-edit",
+ "width": 768,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "Редактирование проекта\nудалить проект\nсохранить черновик\nотправить заявку\nосновные данные\nпартнеры и ресурсы\nдостижения\nвакансии\nкоманда\nданные для конкурсов\nлоготип\nпрезентация\n\nПрезентации формата .PDF\nили .PPTX весом до 50МБ\n\nобложка\n\nСтандартная обложка\n\nЗагрузить файл\n1\nназвание\n\n17 / 256\n\nреги"
+ }
+]
diff --git a/docs/desktop-regression/mobile-after.json b/docs/desktop-regression/mobile-after.json
new file mode 100644
index 000000000..b58970f67
--- /dev/null
+++ b/docs/desktop-regression/mobile-after.json
@@ -0,0 +1,1772 @@
+[
+ {
+ "name": "feed",
+ "width": 320,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф"
+ },
+ {
+ "name": "projects",
+ "width": 320,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок"
+ },
+ {
+ "name": "my-projects",
+ "width": 320,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд"
+ },
+ {
+ "name": "members",
+ "width": 320,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л"
+ },
+ {
+ "name": "programs",
+ "width": 320,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России"
+ },
+ {
+ "name": "program",
+ "width": 320,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз"
+ },
+ {
+ "name": "profile",
+ "width": 320,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно"
+ },
+ {
+ "name": "project",
+ "width": 320,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ"
+ },
+ {
+ "name": "vacancies",
+ "width": 320,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100000 ₽\n\nМотивированность\n\nГлубинное интервью\n\nПроектирование пользовательского о"
+ },
+ {
+ "name": "vacancy",
+ "width": 320,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "Вакансии\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100 000 ₽\nУдаленная работа\nМосква\nОписание вакансии\nПомогите создавать понятные интерфейсы для студе"
+ },
+ {
+ "name": "courses",
+ "width": 320,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение"
+ },
+ {
+ "name": "course",
+ "width": 320,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar"
+ ],
+ "text": "Курсы\nаналитика\nо курсе\nназад\nвернуться в программу\n\nпрогресс по курсу\n\n10%\n\nМодуль 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\n1 урок\n\n10%"
+ },
+ {
+ "name": "feed",
+ "width": 390,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф"
+ },
+ {
+ "name": "projects",
+ "width": 390,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок"
+ },
+ {
+ "name": "my-projects",
+ "width": 390,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд"
+ },
+ {
+ "name": "members",
+ "width": 390,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л"
+ },
+ {
+ "name": "programs",
+ "width": 390,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России"
+ },
+ {
+ "name": "program",
+ "width": 390,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз"
+ },
+ {
+ "name": "profile",
+ "width": 390,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно"
+ },
+ {
+ "name": "project",
+ "width": 390,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ"
+ },
+ {
+ "name": "vacancies",
+ "width": 390,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100000 ₽\n\nМотивированность\n\nГлубинное интервью\n\nПроектирование пользовательского о"
+ },
+ {
+ "name": "vacancy",
+ "width": 390,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "Вакансии\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100 000 ₽\nУдаленная работа\nМосква\nОписание вакансии\nПомогите создавать понятные интерфейсы для студе"
+ },
+ {
+ "name": "courses",
+ "width": 390,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение"
+ },
+ {
+ "name": "course",
+ "width": 390,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar"
+ ],
+ "text": "Курсы\nаналитика\nо курсе\nназад\nвернуться в программу\n\nпрогресс по курсу\n\n10%\n\nМодуль 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\n1 урок\n\n10%"
+ },
+ {
+ "name": "feed",
+ "width": 768,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф"
+ },
+ {
+ "name": "projects",
+ "width": 768,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок"
+ },
+ {
+ "name": "my-projects",
+ "width": 768,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд"
+ },
+ {
+ "name": "members",
+ "width": 768,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л"
+ },
+ {
+ "name": "programs",
+ "width": 768,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России"
+ },
+ {
+ "name": "program",
+ "width": 768,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз"
+ },
+ {
+ "name": "profile",
+ "width": 768,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно"
+ },
+ {
+ "name": "project",
+ "width": 768,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ"
+ },
+ {
+ "name": "vacancies",
+ "width": 768,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100000 ₽\n\nМотивированность\n\nГлубинное интервью\n\nПроектирование пользовательского о"
+ },
+ {
+ "name": "vacancy",
+ "width": 768,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "Вакансии\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100 000 ₽\nУдаленная работа\nМосква\nОписание вакансии\nПомогите создавать понятные интерфейсы для студе"
+ },
+ {
+ "name": "courses",
+ "width": 768,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение"
+ },
+ {
+ "name": "course",
+ "width": 768,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar"
+ ],
+ "text": "Курсы\nаналитика\nо курсе\nназад\nвернуться в программу\n\nпрогресс по курсу\n\n10%\n\nМодуль 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\n1 урок\n\n10%"
+ }
+]
diff --git a/docs/desktop-regression/mobile-before-edit.json b/docs/desktop-regression/mobile-before-edit.json
new file mode 100644
index 000000000..79ec36bc7
--- /dev/null
+++ b/docs/desktop-regression/mobile-before-edit.json
@@ -0,0 +1,341 @@
+[
+ {
+ "name": "profile-edit",
+ "width": 320,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон"
+ },
+ {
+ "name": "project-edit",
+ "width": 320,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "Редактирование проекта\nудалить проект\nсохранить черновик\nотправить заявку\nосновные данные\nпартнеры и ресурсы\nдостижения\nвакансии\nкоманда\nданные для конкурсов\nлоготип\nпрезентация\n\nПрезентации формата .PDF\nили .PPTX весом до 50МБ\n\nобложка\n\nСтандартная обложка\n\nЗагрузить файл\n1\nназвание\n\n17 / 256\n\nреги"
+ },
+ {
+ "name": "profile-edit",
+ "width": 390,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон"
+ },
+ {
+ "name": "project-edit",
+ "width": 390,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "Редактирование проекта\nудалить проект\nсохранить черновик\nотправить заявку\nосновные данные\nпартнеры и ресурсы\nдостижения\nвакансии\nкоманда\nданные для конкурсов\nлоготип\nпрезентация\n\nПрезентации формата .PDF\nили .PPTX весом до 50МБ\n\nобложка\n\nСтандартная обложка\n\nЗагрузить файл\n1\nназвание\n\n17 / 256\n\nреги"
+ },
+ {
+ "name": "profile-edit",
+ "width": 768,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон"
+ },
+ {
+ "name": "project-edit",
+ "width": 768,
+ "actualPath": "/office/projects/1/edit",
+ "actualQuery": "?editingStep=main&programLinkId=1",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-modal",
+ "app-upload-file",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-region-select",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-edit",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-project-main-step",
+ "app-avatar-control",
+ "app-tooltip",
+ "app-upload-file",
+ "app-select",
+ "app-input",
+ "app-region-select",
+ "app-textarea"
+ ],
+ "text": "Редактирование проекта\nудалить проект\nсохранить черновик\nотправить заявку\nосновные данные\nпартнеры и ресурсы\nдостижения\nвакансии\nкоманда\nданные для конкурсов\nлоготип\nпрезентация\n\nПрезентации формата .PDF\nили .PPTX весом до 50МБ\n\nобложка\n\nСтандартная обложка\n\nЗагрузить файл\n1\nназвание\n\n17 / 256\n\nреги"
+ }
+]
diff --git a/docs/desktop-regression/mobile-before.json b/docs/desktop-regression/mobile-before.json
new file mode 100644
index 000000000..b58970f67
--- /dev/null
+++ b/docs/desktop-regression/mobile-before.json
@@ -0,0 +1,1772 @@
+[
+ {
+ "name": "feed",
+ "width": 320,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф"
+ },
+ {
+ "name": "projects",
+ "width": 320,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок"
+ },
+ {
+ "name": "my-projects",
+ "width": 320,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд"
+ },
+ {
+ "name": "members",
+ "width": 320,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л"
+ },
+ {
+ "name": "programs",
+ "width": 320,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России"
+ },
+ {
+ "name": "program",
+ "width": 320,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз"
+ },
+ {
+ "name": "profile",
+ "width": 320,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно"
+ },
+ {
+ "name": "project",
+ "width": 320,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ"
+ },
+ {
+ "name": "vacancies",
+ "width": 320,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100000 ₽\n\nМотивированность\n\nГлубинное интервью\n\nПроектирование пользовательского о"
+ },
+ {
+ "name": "vacancy",
+ "width": 320,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "Вакансии\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100 000 ₽\nУдаленная работа\nМосква\nОписание вакансии\nПомогите создавать понятные интерфейсы для студе"
+ },
+ {
+ "name": "courses",
+ "width": 320,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение"
+ },
+ {
+ "name": "course",
+ "width": 320,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar"
+ ],
+ "text": "Курсы\nаналитика\nо курсе\nназад\nвернуться в программу\n\nпрогресс по курсу\n\n10%\n\nМодуль 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\n1 урок\n\n10%"
+ },
+ {
+ "name": "feed",
+ "width": 390,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф"
+ },
+ {
+ "name": "projects",
+ "width": 390,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок"
+ },
+ {
+ "name": "my-projects",
+ "width": 390,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд"
+ },
+ {
+ "name": "members",
+ "width": 390,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л"
+ },
+ {
+ "name": "programs",
+ "width": 390,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России"
+ },
+ {
+ "name": "program",
+ "width": 390,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз"
+ },
+ {
+ "name": "profile",
+ "width": 390,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно"
+ },
+ {
+ "name": "project",
+ "width": 390,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ"
+ },
+ {
+ "name": "vacancies",
+ "width": 390,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100000 ₽\n\nМотивированность\n\nГлубинное интервью\n\nПроектирование пользовательского о"
+ },
+ {
+ "name": "vacancy",
+ "width": 390,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "Вакансии\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100 000 ₽\nУдаленная работа\nМосква\nОписание вакансии\nПомогите создавать понятные интерфейсы для студе"
+ },
+ {
+ "name": "courses",
+ "width": 390,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение"
+ },
+ {
+ "name": "course",
+ "width": 390,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar"
+ ],
+ "text": "Курсы\nаналитика\nо курсе\nназад\nвернуться в программу\n\nпрогресс по курсу\n\n10%\n\nМодуль 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\n1 урок\n\n10%"
+ },
+ {
+ "name": "feed",
+ "width": 768,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф"
+ },
+ {
+ "name": "projects",
+ "width": 768,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок"
+ },
+ {
+ "name": "my-projects",
+ "width": 768,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд"
+ },
+ {
+ "name": "members",
+ "width": 768,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л"
+ },
+ {
+ "name": "programs",
+ "width": 768,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России"
+ },
+ {
+ "name": "program",
+ "width": 768,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз"
+ },
+ {
+ "name": "profile",
+ "width": 768,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно"
+ },
+ {
+ "name": "project",
+ "width": 768,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ"
+ },
+ {
+ "name": "vacancies",
+ "width": 768,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nДизайнер интерфейсов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100000 ₽\n\nМотивированность\n\nГлубинное интервью\n\nПроектирование пользовательского о"
+ },
+ {
+ "name": "vacancy",
+ "width": 768,
+ "actualPath": "/office/vacancies/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies-detail",
+ "app-back",
+ "app-vacancy-status",
+ "app-badge",
+ "app-detail",
+ "app-vacancies-left-side",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-vacancies-right-side",
+ "app-button"
+ ],
+ "text": "Вакансии\nВакансии\nДизайнер интерфейсов\nАктивна\nПроект: ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nИщем: Разработчик\n\n100 000 ₽\nУдаленная работа\nМосква\nОписание вакансии\nПомогите создавать понятные интерфейсы для студе"
+ },
+ {
+ "name": "courses",
+ "width": 768,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение"
+ },
+ {
+ "name": "course",
+ "width": 768,
+ "actualPath": "/office/courses/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-detail",
+ "app-course-module-card",
+ "app-circle-progress-bar"
+ ],
+ "text": "Курсы\nаналитика\nо курсе\nназад\nвернуться в программу\n\nпрогресс по курсу\n\n10%\n\nМодуль 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\n1 урок\n\n10%"
+ }
+]
diff --git a/docs/desktop-regression/resize.cjs b/docs/desktop-regression/resize.cjs
new file mode 100644
index 000000000..49450b566
--- /dev/null
+++ b/docs/desktop-regression/resize.cjs
@@ -0,0 +1,74 @@
+/** @format */
+
+const assert = require("node:assert/strict");
+const fs = require("node:fs");
+const { launch, assertViewport } = require("../responsive/browser-harness.cjs");
+require("../mobile-polish/fixtures.cjs");
+(async () => {
+ const h = await launch(390);
+ const rows = [];
+ try {
+ await h.page.goto(h.base + "/office/feed");
+ await h.page.waitForLoadState("networkidle");
+ await h.page.getByRole("button", { name: /свежие вакансии/ }).click();
+ await h.page.waitForLoadState("networkidle");
+ await h.page.evaluate(() => {
+ window.qaFeedRoot = document.querySelector("app-feed .page");
+ if (!window.qaFeedRoot) throw new Error("Feed root missing");
+ });
+ const query = new URL(h.page.url()).search;
+ for (const width of [1000, 768, 390]) {
+ await h.page.setViewportSize({ width, height: 844 });
+ await h.page.waitForFunction(width => innerWidth === width, width);
+ await h.page.waitForFunction(
+ width => !!document.querySelector("button.control-panel__action") === width < 1000,
+ width,
+ );
+ await assertViewport(h.page);
+ assert.equal(new URL(h.page.url()).search, query);
+ assert.equal(
+ await h.page.evaluate(() => window.qaFeedRoot === document.querySelector("app-feed .page")),
+ true,
+ );
+ rows.push({ screen: "feed", width, preserved: true });
+ }
+ await h.page.evaluate(() => {
+ history.pushState({}, "", "/office/projects/dashboard");
+ dispatchEvent(new PopStateEvent("popstate"));
+ });
+ await h.page.locator("app-dashboard-item").first().waitFor();
+ const input = h.page.locator("app-projects app-search input");
+ await h.page.locator("app-projects app-search .search").click();
+ await input.fill("город");
+ await h.page.waitForTimeout(500); // Existing search debounce.
+ await h.page.evaluate(() => {
+ window.qaDashboard = document.querySelector("app-dashboard-item").parentElement;
+ });
+ const route = h.page.url();
+ for (const width of [1000, 768, 390]) {
+ await h.page.setViewportSize({ width, height: 844 });
+ await h.page.waitForFunction(
+ width => !!document.querySelector("app-projects app-page-header") === width < 1000,
+ width,
+ );
+ await assertViewport(h.page);
+ assert.equal(await input.inputValue(), "город");
+ assert.equal(h.page.url(), route);
+ assert.equal(
+ await h.page.evaluate(
+ () => window.qaDashboard === document.querySelector("app-dashboard-item").parentElement,
+ ),
+ true,
+ );
+ rows.push({ screen: "projects", width, preserved: true });
+ }
+ assert.deepEqual(h.errors, []);
+ fs.writeFileSync(__dirname + "/resize.json", JSON.stringify(rows, null, 2) + "\n");
+ console.log("6 resize checks passed; routed hosts, search and filters preserved");
+ } finally {
+ await h.browser.close();
+ }
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/desktop-regression/resize.json b/docs/desktop-regression/resize.json
new file mode 100644
index 000000000..0441fe358
--- /dev/null
+++ b/docs/desktop-regression/resize.json
@@ -0,0 +1,32 @@
+[
+ {
+ "screen": "feed",
+ "width": 1000,
+ "preserved": true
+ },
+ {
+ "screen": "feed",
+ "width": 768,
+ "preserved": true
+ },
+ {
+ "screen": "feed",
+ "width": 390,
+ "preserved": true
+ },
+ {
+ "screen": "projects",
+ "width": 1000,
+ "preserved": true
+ },
+ {
+ "screen": "projects",
+ "width": 768,
+ "preserved": true
+ },
+ {
+ "screen": "projects",
+ "width": 390,
+ "preserved": true
+ }
+]
diff --git a/docs/desktop-regression/review.md b/docs/desktop-regression/review.md
new file mode 100644
index 000000000..a95092fa9
--- /dev/null
+++ b/docs/desktop-regression/review.md
@@ -0,0 +1,67 @@
+
+
+# Requirement audit и review
+
+Scope: восстановить desktop `dev` до #401 и сохранить адаптив из #403.
+Review выполнен в текущей задаче по `procollab-review`, PR preparation — по `procollab-pr`.
+Visual reference задан пользователем; новое продуктовое/design решение не вводилось.
+
+| AC | Реализация / evidence | Verdict |
+| ------------------------------------------ | ---------------------------------------------------------------------------------------- | --------------------------------------- |
+| Desktop ≥1000 сохраняет прежнюю композицию | Scoped styles и legacy fragments; 36 exact pixel comparisons с `5fe4d5c6` | PASS |
+| Приоритетные разделы и shared Button/Card | 14 экранов + 3 empty states + loading action на 1440/1920; [сравнение](README.md) | PASS |
+| Pixel regression обязателен | `compare.py --check`: размер + exact RGB; reference repeat и after: 36/36, 0 pixels | PASS |
+| Mobile/tablet сохраняется | 42 exact comparisons с `1138fe0c` на 320/390/768; 48 states, 18 interactions | PASS |
+| Breakpoint не сбрасывает текущую страницу | 6 resize checks: same DOM roots, search value, route/filter query сохранены | PASS |
+| API/permissions/business rules сохранены | Нет diff в API/domain/infrastructure, DTO, routes, dependencies; прежние handlers/guards | PASS by source + unit/integration tests |
+
+## Checked by source
+
+- Media boundary `<1000px` и desktop legacy values, canonical Button/Avatar/Icon consumers.
+- Presentation service не содержит domain/API решений. Корни router/search/forms не дублируются.
+- Имеющиеся role conditions и handlers сохранены в обеих presentation-ветках.
+- Forms/CVA, save/autosave services, HTTP contracts, IDs, server-owned permissions и deadlines не менялись.
+- `git diff --exit-code origin/dev -- projects/social_platform/src/app/api projects/social_platform/src/app/domain projects/social_platform/src/app/infrastructure package.json package-lock.json angular.json` — пустой diff.
+- Дополнительно восстановлена desktop ширина 605 px двух информационных диалогов редактора проекта.
+
+## Checked by tests / build
+
+- `npm run test:ci`: 2006 tests, 406 files. Runner по-прежнему исключает
+ `projects.component.spec.ts`, `program.component.spec.ts`, `editor-submit-button.directive.spec.ts`.
+- Placement regression проверяет условия размещения activity через Angular template AST.
+- `npm run build:social:prod`: успешная компиляция TypeScript/templates/styles, budgets сохранены.
+- `npm run lint:ts`: 0 errors, 6 прежних warnings. SCSS проверен на изменённых файлах.
+
+## Checked in browser
+
+- Windows / installed Chrome / одинаковые fixture responses и browser context.
+- Desktop reference repeat, before/after, mobile before/after: strict pixel equality, без masks.
+- Loading page/action, pending action без повторного запроса, empty, HTTP 500/retry,
+ disabled controls и validation регистрации/onboarding: [48 checks](states.json).
+- Центр мобильной шапки, drawer route transition/Escape/focus return, notifications с клавиатуры,
+ filter query/request, полные навыки, карточки и Detail actions: [18 checks](interactions.json).
+- Поиск/фильтр после resize: [6 checks](resize.json).
+
+## Findings и устранение
+
+- MAJOR: общие UI Kit геометрия/типографика меняли desktop consumers. Ограничены mobile,
+ прежние desktop styles/markup восстановлены; exact comparisons проходят.
+- MAJOR: shared Tabs заменили прежнюю desktop step navigation. Legacy desktop markup восстановлен,
+ оба редактора включены в pixel comparison.
+- MINOR: медиа-обёртка изменила CSS cascade полей и их mobile padding. Сохранён исходный
+ каскад responsive controls, повторные сравнения editor ширин проходят.
+- Test harness: Escape отправлялся до появления drawer и захвата фокуса. Теперь проверка ждёт
+ реальный dialog/focus, затем проверяет закрытие и возврат фокуса; assertions не ослаблены.
+
+Нерешённых actionable findings в проверенном scope нет.
+
+## Not checked / limits
+
+- Реальные iOS/Android на dev и production. Device smoke-test после merge остаётся обязательным.
+- Live backend данные и полный role matrix; server permissions не изменялись и заново не аудировались.
+- Каждый скрытый scroll section, popup и возможный async state не покрыт pixel screenshots.
+ Desktop pixel states: empty feed/vacancies/courses и loading action; остальные error/disabled/validation покрыты mobile state checks.
+- Onboarding desktop не входит в набор desktop pixel goldens; его прежняя геометрия восстановлена по source.
+
+Verdict: READY TO MERGE INTO DEV для реализации. Dev acceptance и физический device smoke-test
+требуются после merge перед production handoff.
diff --git a/docs/desktop-regression/screenshots/desktop-after/course-1440.png b/docs/desktop-regression/screenshots/desktop-after/course-1440.png
new file mode 100644
index 000000000..28fc758f0
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/course-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/course-1920.png b/docs/desktop-regression/screenshots/desktop-after/course-1920.png
new file mode 100644
index 000000000..a9a068cdb
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/course-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/courses-1440.png b/docs/desktop-regression/screenshots/desktop-after/courses-1440.png
new file mode 100644
index 000000000..cbe2f3efa
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/courses-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/courses-1920.png b/docs/desktop-regression/screenshots/desktop-after/courses-1920.png
new file mode 100644
index 000000000..97aff998b
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/courses-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/empty-courses-1440.png b/docs/desktop-regression/screenshots/desktop-after/empty-courses-1440.png
new file mode 100644
index 000000000..a64d1a410
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/empty-courses-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/empty-courses-1920.png b/docs/desktop-regression/screenshots/desktop-after/empty-courses-1920.png
new file mode 100644
index 000000000..f2afde1ca
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/empty-courses-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/empty-feed-1440.png b/docs/desktop-regression/screenshots/desktop-after/empty-feed-1440.png
new file mode 100644
index 000000000..390f08614
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/empty-feed-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/empty-feed-1920.png b/docs/desktop-regression/screenshots/desktop-after/empty-feed-1920.png
new file mode 100644
index 000000000..8021bdd96
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/empty-feed-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/empty-vacancies-1440.png b/docs/desktop-regression/screenshots/desktop-after/empty-vacancies-1440.png
new file mode 100644
index 000000000..25e0d187d
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/empty-vacancies-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/empty-vacancies-1920.png b/docs/desktop-regression/screenshots/desktop-after/empty-vacancies-1920.png
new file mode 100644
index 000000000..f0d772dbc
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/empty-vacancies-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/feed-1440.png b/docs/desktop-regression/screenshots/desktop-after/feed-1440.png
new file mode 100644
index 000000000..5c1f6b5ba
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/feed-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/feed-1920.png b/docs/desktop-regression/screenshots/desktop-after/feed-1920.png
new file mode 100644
index 000000000..dbbc494e2
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/feed-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/loading-action-1440.png b/docs/desktop-regression/screenshots/desktop-after/loading-action-1440.png
new file mode 100644
index 000000000..f9a423c68
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/loading-action-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/loading-action-1920.png b/docs/desktop-regression/screenshots/desktop-after/loading-action-1920.png
new file mode 100644
index 000000000..ab14093b0
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/loading-action-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/members-1440.png b/docs/desktop-regression/screenshots/desktop-after/members-1440.png
new file mode 100644
index 000000000..82ba26d32
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/members-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/members-1920.png b/docs/desktop-regression/screenshots/desktop-after/members-1920.png
new file mode 100644
index 000000000..88d9735d1
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/members-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/my-projects-1440.png b/docs/desktop-regression/screenshots/desktop-after/my-projects-1440.png
new file mode 100644
index 000000000..b68148c3c
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/my-projects-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/my-projects-1920.png b/docs/desktop-regression/screenshots/desktop-after/my-projects-1920.png
new file mode 100644
index 000000000..f35605787
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/my-projects-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/profile-1440.png b/docs/desktop-regression/screenshots/desktop-after/profile-1440.png
new file mode 100644
index 000000000..bdf7b8893
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/profile-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/profile-1920.png b/docs/desktop-regression/screenshots/desktop-after/profile-1920.png
new file mode 100644
index 000000000..694c06e11
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/profile-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/profile-edit-1440.png b/docs/desktop-regression/screenshots/desktop-after/profile-edit-1440.png
new file mode 100644
index 000000000..c476a08d3
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/profile-edit-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/profile-edit-1920.png b/docs/desktop-regression/screenshots/desktop-after/profile-edit-1920.png
new file mode 100644
index 000000000..c5375fb79
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/profile-edit-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/program-1440.png b/docs/desktop-regression/screenshots/desktop-after/program-1440.png
new file mode 100644
index 000000000..d75134d8d
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/program-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/program-1920.png b/docs/desktop-regression/screenshots/desktop-after/program-1920.png
new file mode 100644
index 000000000..a6533d244
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/program-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/programs-1440.png b/docs/desktop-regression/screenshots/desktop-after/programs-1440.png
new file mode 100644
index 000000000..bd1e531bd
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/programs-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/programs-1920.png b/docs/desktop-regression/screenshots/desktop-after/programs-1920.png
new file mode 100644
index 000000000..2ac2fca15
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/programs-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/project-1440.png b/docs/desktop-regression/screenshots/desktop-after/project-1440.png
new file mode 100644
index 000000000..ca9c33f86
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/project-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/project-1920.png b/docs/desktop-regression/screenshots/desktop-after/project-1920.png
new file mode 100644
index 000000000..57b237a69
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/project-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/project-edit-1440.png b/docs/desktop-regression/screenshots/desktop-after/project-edit-1440.png
new file mode 100644
index 000000000..bd450be9c
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/project-edit-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/project-edit-1920.png b/docs/desktop-regression/screenshots/desktop-after/project-edit-1920.png
new file mode 100644
index 000000000..1e66e1a61
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/project-edit-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/projects-1440.png b/docs/desktop-regression/screenshots/desktop-after/projects-1440.png
new file mode 100644
index 000000000..80253540a
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/projects-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/projects-1920.png b/docs/desktop-regression/screenshots/desktop-after/projects-1920.png
new file mode 100644
index 000000000..ed8ded08e
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/projects-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/vacancies-1440.png b/docs/desktop-regression/screenshots/desktop-after/vacancies-1440.png
new file mode 100644
index 000000000..cffaf991b
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/vacancies-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/vacancies-1920.png b/docs/desktop-regression/screenshots/desktop-after/vacancies-1920.png
new file mode 100644
index 000000000..da5a70205
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/vacancies-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/vacancy-1440.png b/docs/desktop-regression/screenshots/desktop-after/vacancy-1440.png
new file mode 100644
index 000000000..bb61fa169
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/vacancy-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-after/vacancy-1920.png b/docs/desktop-regression/screenshots/desktop-after/vacancy-1920.png
new file mode 100644
index 000000000..7b456f551
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-after/vacancy-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/course-1440.png b/docs/desktop-regression/screenshots/desktop-before/course-1440.png
new file mode 100644
index 000000000..28fc758f0
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/course-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/course-1920.png b/docs/desktop-regression/screenshots/desktop-before/course-1920.png
new file mode 100644
index 000000000..a9a068cdb
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/course-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/courses-1440.png b/docs/desktop-regression/screenshots/desktop-before/courses-1440.png
new file mode 100644
index 000000000..cbe2f3efa
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/courses-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/courses-1920.png b/docs/desktop-regression/screenshots/desktop-before/courses-1920.png
new file mode 100644
index 000000000..97aff998b
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/courses-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/empty-courses-1440.png b/docs/desktop-regression/screenshots/desktop-before/empty-courses-1440.png
new file mode 100644
index 000000000..a64d1a410
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/empty-courses-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/empty-courses-1920.png b/docs/desktop-regression/screenshots/desktop-before/empty-courses-1920.png
new file mode 100644
index 000000000..f2afde1ca
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/empty-courses-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/empty-feed-1440.png b/docs/desktop-regression/screenshots/desktop-before/empty-feed-1440.png
new file mode 100644
index 000000000..390f08614
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/empty-feed-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/empty-feed-1920.png b/docs/desktop-regression/screenshots/desktop-before/empty-feed-1920.png
new file mode 100644
index 000000000..8021bdd96
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/empty-feed-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/empty-vacancies-1440.png b/docs/desktop-regression/screenshots/desktop-before/empty-vacancies-1440.png
new file mode 100644
index 000000000..25e0d187d
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/empty-vacancies-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/empty-vacancies-1920.png b/docs/desktop-regression/screenshots/desktop-before/empty-vacancies-1920.png
new file mode 100644
index 000000000..f0d772dbc
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/empty-vacancies-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/feed-1440.png b/docs/desktop-regression/screenshots/desktop-before/feed-1440.png
new file mode 100644
index 000000000..5c1f6b5ba
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/feed-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/feed-1920.png b/docs/desktop-regression/screenshots/desktop-before/feed-1920.png
new file mode 100644
index 000000000..dbbc494e2
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/feed-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/loading-action-1440.png b/docs/desktop-regression/screenshots/desktop-before/loading-action-1440.png
new file mode 100644
index 000000000..f9a423c68
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/loading-action-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/loading-action-1920.png b/docs/desktop-regression/screenshots/desktop-before/loading-action-1920.png
new file mode 100644
index 000000000..ab14093b0
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/loading-action-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/members-1440.png b/docs/desktop-regression/screenshots/desktop-before/members-1440.png
new file mode 100644
index 000000000..82ba26d32
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/members-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/members-1920.png b/docs/desktop-regression/screenshots/desktop-before/members-1920.png
new file mode 100644
index 000000000..88d9735d1
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/members-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/my-projects-1440.png b/docs/desktop-regression/screenshots/desktop-before/my-projects-1440.png
new file mode 100644
index 000000000..b68148c3c
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/my-projects-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/my-projects-1920.png b/docs/desktop-regression/screenshots/desktop-before/my-projects-1920.png
new file mode 100644
index 000000000..f35605787
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/my-projects-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/profile-1440.png b/docs/desktop-regression/screenshots/desktop-before/profile-1440.png
new file mode 100644
index 000000000..bdf7b8893
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/profile-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/profile-1920.png b/docs/desktop-regression/screenshots/desktop-before/profile-1920.png
new file mode 100644
index 000000000..694c06e11
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/profile-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/profile-edit-1440.png b/docs/desktop-regression/screenshots/desktop-before/profile-edit-1440.png
new file mode 100644
index 000000000..c476a08d3
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/profile-edit-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/profile-edit-1920.png b/docs/desktop-regression/screenshots/desktop-before/profile-edit-1920.png
new file mode 100644
index 000000000..c5375fb79
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/profile-edit-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/program-1440.png b/docs/desktop-regression/screenshots/desktop-before/program-1440.png
new file mode 100644
index 000000000..d75134d8d
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/program-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/program-1920.png b/docs/desktop-regression/screenshots/desktop-before/program-1920.png
new file mode 100644
index 000000000..a6533d244
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/program-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/programs-1440.png b/docs/desktop-regression/screenshots/desktop-before/programs-1440.png
new file mode 100644
index 000000000..bd1e531bd
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/programs-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/programs-1920.png b/docs/desktop-regression/screenshots/desktop-before/programs-1920.png
new file mode 100644
index 000000000..2ac2fca15
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/programs-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/project-1440.png b/docs/desktop-regression/screenshots/desktop-before/project-1440.png
new file mode 100644
index 000000000..ca9c33f86
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/project-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/project-1920.png b/docs/desktop-regression/screenshots/desktop-before/project-1920.png
new file mode 100644
index 000000000..57b237a69
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/project-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/project-edit-1440.png b/docs/desktop-regression/screenshots/desktop-before/project-edit-1440.png
new file mode 100644
index 000000000..bd450be9c
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/project-edit-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/project-edit-1920.png b/docs/desktop-regression/screenshots/desktop-before/project-edit-1920.png
new file mode 100644
index 000000000..1e66e1a61
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/project-edit-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/projects-1440.png b/docs/desktop-regression/screenshots/desktop-before/projects-1440.png
new file mode 100644
index 000000000..80253540a
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/projects-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/projects-1920.png b/docs/desktop-regression/screenshots/desktop-before/projects-1920.png
new file mode 100644
index 000000000..ed8ded08e
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/projects-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/vacancies-1440.png b/docs/desktop-regression/screenshots/desktop-before/vacancies-1440.png
new file mode 100644
index 000000000..cffaf991b
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/vacancies-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/vacancies-1920.png b/docs/desktop-regression/screenshots/desktop-before/vacancies-1920.png
new file mode 100644
index 000000000..da5a70205
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/vacancies-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/vacancy-1440.png b/docs/desktop-regression/screenshots/desktop-before/vacancy-1440.png
new file mode 100644
index 000000000..bb61fa169
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/vacancy-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-before/vacancy-1920.png b/docs/desktop-regression/screenshots/desktop-before/vacancy-1920.png
new file mode 100644
index 000000000..7b456f551
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-before/vacancy-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/course-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/course-1440.png
new file mode 100644
index 000000000..28fc758f0
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/course-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/course-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/course-1920.png
new file mode 100644
index 000000000..a9a068cdb
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/course-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/courses-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/courses-1440.png
new file mode 100644
index 000000000..cbe2f3efa
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/courses-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/courses-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/courses-1920.png
new file mode 100644
index 000000000..97aff998b
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/courses-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/empty-courses-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/empty-courses-1440.png
new file mode 100644
index 000000000..a64d1a410
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/empty-courses-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/empty-courses-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/empty-courses-1920.png
new file mode 100644
index 000000000..f2afde1ca
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/empty-courses-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/empty-feed-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/empty-feed-1440.png
new file mode 100644
index 000000000..390f08614
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/empty-feed-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/empty-feed-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/empty-feed-1920.png
new file mode 100644
index 000000000..8021bdd96
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/empty-feed-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/empty-vacancies-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/empty-vacancies-1440.png
new file mode 100644
index 000000000..25e0d187d
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/empty-vacancies-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/empty-vacancies-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/empty-vacancies-1920.png
new file mode 100644
index 000000000..f0d772dbc
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/empty-vacancies-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/feed-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/feed-1440.png
new file mode 100644
index 000000000..5c1f6b5ba
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/feed-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/feed-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/feed-1920.png
new file mode 100644
index 000000000..dbbc494e2
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/feed-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/loading-action-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/loading-action-1440.png
new file mode 100644
index 000000000..f9a423c68
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/loading-action-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/loading-action-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/loading-action-1920.png
new file mode 100644
index 000000000..ab14093b0
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/loading-action-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/members-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/members-1440.png
new file mode 100644
index 000000000..82ba26d32
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/members-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/members-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/members-1920.png
new file mode 100644
index 000000000..88d9735d1
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/members-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/my-projects-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/my-projects-1440.png
new file mode 100644
index 000000000..b68148c3c
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/my-projects-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/my-projects-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/my-projects-1920.png
new file mode 100644
index 000000000..f35605787
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/my-projects-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/profile-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/profile-1440.png
new file mode 100644
index 000000000..bdf7b8893
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/profile-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/profile-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/profile-1920.png
new file mode 100644
index 000000000..694c06e11
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/profile-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/profile-edit-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/profile-edit-1440.png
new file mode 100644
index 000000000..c476a08d3
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/profile-edit-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/profile-edit-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/profile-edit-1920.png
new file mode 100644
index 000000000..c5375fb79
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/profile-edit-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/program-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/program-1440.png
new file mode 100644
index 000000000..d75134d8d
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/program-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/program-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/program-1920.png
new file mode 100644
index 000000000..a6533d244
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/program-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/programs-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/programs-1440.png
new file mode 100644
index 000000000..bd1e531bd
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/programs-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/programs-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/programs-1920.png
new file mode 100644
index 000000000..2ac2fca15
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/programs-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/project-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/project-1440.png
new file mode 100644
index 000000000..ca9c33f86
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/project-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/project-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/project-1920.png
new file mode 100644
index 000000000..57b237a69
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/project-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/project-edit-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/project-edit-1440.png
new file mode 100644
index 000000000..bd450be9c
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/project-edit-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/project-edit-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/project-edit-1920.png
new file mode 100644
index 000000000..1e66e1a61
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/project-edit-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/projects-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/projects-1440.png
new file mode 100644
index 000000000..80253540a
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/projects-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/projects-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/projects-1920.png
new file mode 100644
index 000000000..ed8ded08e
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/projects-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/vacancies-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/vacancies-1440.png
new file mode 100644
index 000000000..cffaf991b
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/vacancies-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/vacancies-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/vacancies-1920.png
new file mode 100644
index 000000000..da5a70205
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/vacancies-1920.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/vacancy-1440.png b/docs/desktop-regression/screenshots/desktop-repeat/vacancy-1440.png
new file mode 100644
index 000000000..bb61fa169
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/vacancy-1440.png differ
diff --git a/docs/desktop-regression/screenshots/desktop-repeat/vacancy-1920.png b/docs/desktop-regression/screenshots/desktop-repeat/vacancy-1920.png
new file mode 100644
index 000000000..7b456f551
Binary files /dev/null and b/docs/desktop-regression/screenshots/desktop-repeat/vacancy-1920.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/members-320.png b/docs/desktop-regression/screenshots/interactions/members-320.png
new file mode 100644
index 000000000..a2d5c15a9
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/members-320.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/members-390.png b/docs/desktop-regression/screenshots/interactions/members-390.png
new file mode 100644
index 000000000..006cc3b44
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/members-390.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/members-768.png b/docs/desktop-regression/screenshots/interactions/members-768.png
new file mode 100644
index 000000000..3f2af2700
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/members-768.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-320.png b/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-320.png
new file mode 100644
index 000000000..bb3fd309b
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-320.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-390.png b/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-390.png
new file mode 100644
index 000000000..e9df351e7
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-390.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-768.png b/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-768.png
new file mode 100644
index 000000000..27b430248
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/navigation-feed-skills-768.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/profile-actions-320.png b/docs/desktop-regression/screenshots/interactions/profile-actions-320.png
new file mode 100644
index 000000000..6d986bb01
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/profile-actions-320.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/profile-actions-390.png b/docs/desktop-regression/screenshots/interactions/profile-actions-390.png
new file mode 100644
index 000000000..3dc0eef00
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/profile-actions-390.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/profile-actions-768.png b/docs/desktop-regression/screenshots/interactions/profile-actions-768.png
new file mode 100644
index 000000000..2792b9133
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/profile-actions-768.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/program-actions-320.png b/docs/desktop-regression/screenshots/interactions/program-actions-320.png
new file mode 100644
index 000000000..d227b6fc7
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/program-actions-320.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/program-actions-390.png b/docs/desktop-regression/screenshots/interactions/program-actions-390.png
new file mode 100644
index 000000000..ca42ebed2
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/program-actions-390.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/program-actions-768.png b/docs/desktop-regression/screenshots/interactions/program-actions-768.png
new file mode 100644
index 000000000..6eb899bf8
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/program-actions-768.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/project-actions-320.png b/docs/desktop-regression/screenshots/interactions/project-actions-320.png
new file mode 100644
index 000000000..270a2d0b3
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/project-actions-320.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/project-actions-390.png b/docs/desktop-regression/screenshots/interactions/project-actions-390.png
new file mode 100644
index 000000000..28c978850
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/project-actions-390.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/project-actions-768.png b/docs/desktop-regression/screenshots/interactions/project-actions-768.png
new file mode 100644
index 000000000..4b4882ef2
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/project-actions-768.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/projects-activity-320.png b/docs/desktop-regression/screenshots/interactions/projects-activity-320.png
new file mode 100644
index 000000000..2bae40960
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/projects-activity-320.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/projects-activity-390.png b/docs/desktop-regression/screenshots/interactions/projects-activity-390.png
new file mode 100644
index 000000000..e45c85ef0
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/projects-activity-390.png differ
diff --git a/docs/desktop-regression/screenshots/interactions/projects-activity-768.png b/docs/desktop-regression/screenshots/interactions/projects-activity-768.png
new file mode 100644
index 000000000..52815ac85
Binary files /dev/null and b/docs/desktop-regression/screenshots/interactions/projects-activity-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/course-320.png b/docs/desktop-regression/screenshots/mobile-after/course-320.png
new file mode 100644
index 000000000..a142af53d
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/course-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/course-390.png b/docs/desktop-regression/screenshots/mobile-after/course-390.png
new file mode 100644
index 000000000..febe2a0d9
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/course-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/course-768.png b/docs/desktop-regression/screenshots/mobile-after/course-768.png
new file mode 100644
index 000000000..a0d36aba7
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/course-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/courses-320.png b/docs/desktop-regression/screenshots/mobile-after/courses-320.png
new file mode 100644
index 000000000..c03bda60e
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/courses-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/courses-390.png b/docs/desktop-regression/screenshots/mobile-after/courses-390.png
new file mode 100644
index 000000000..9313fe831
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/courses-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/courses-768.png b/docs/desktop-regression/screenshots/mobile-after/courses-768.png
new file mode 100644
index 000000000..afd420a3d
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/courses-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/feed-320.png b/docs/desktop-regression/screenshots/mobile-after/feed-320.png
new file mode 100644
index 000000000..c408ae762
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/feed-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/feed-390.png b/docs/desktop-regression/screenshots/mobile-after/feed-390.png
new file mode 100644
index 000000000..bc1e6810b
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/feed-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/feed-768.png b/docs/desktop-regression/screenshots/mobile-after/feed-768.png
new file mode 100644
index 000000000..ca58289fd
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/feed-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/members-320.png b/docs/desktop-regression/screenshots/mobile-after/members-320.png
new file mode 100644
index 000000000..a2d5c15a9
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/members-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/members-390.png b/docs/desktop-regression/screenshots/mobile-after/members-390.png
new file mode 100644
index 000000000..006cc3b44
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/members-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/members-768.png b/docs/desktop-regression/screenshots/mobile-after/members-768.png
new file mode 100644
index 000000000..3f2af2700
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/members-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/my-projects-320.png b/docs/desktop-regression/screenshots/mobile-after/my-projects-320.png
new file mode 100644
index 000000000..0eb539b2f
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/my-projects-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/my-projects-390.png b/docs/desktop-regression/screenshots/mobile-after/my-projects-390.png
new file mode 100644
index 000000000..fdf04c57e
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/my-projects-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/my-projects-768.png b/docs/desktop-regression/screenshots/mobile-after/my-projects-768.png
new file mode 100644
index 000000000..e8b7c1c01
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/my-projects-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/profile-320.png b/docs/desktop-regression/screenshots/mobile-after/profile-320.png
new file mode 100644
index 000000000..6d986bb01
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/profile-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/profile-390.png b/docs/desktop-regression/screenshots/mobile-after/profile-390.png
new file mode 100644
index 000000000..3dc0eef00
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/profile-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/profile-768.png b/docs/desktop-regression/screenshots/mobile-after/profile-768.png
new file mode 100644
index 000000000..2792b9133
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/profile-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/profile-edit-320.png b/docs/desktop-regression/screenshots/mobile-after/profile-edit-320.png
new file mode 100644
index 000000000..30a3add05
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/profile-edit-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/profile-edit-390.png b/docs/desktop-regression/screenshots/mobile-after/profile-edit-390.png
new file mode 100644
index 000000000..eb3c0813f
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/profile-edit-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/profile-edit-768.png b/docs/desktop-regression/screenshots/mobile-after/profile-edit-768.png
new file mode 100644
index 000000000..ae37f77fb
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/profile-edit-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/program-320.png b/docs/desktop-regression/screenshots/mobile-after/program-320.png
new file mode 100644
index 000000000..d227b6fc7
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/program-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/program-390.png b/docs/desktop-regression/screenshots/mobile-after/program-390.png
new file mode 100644
index 000000000..ca42ebed2
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/program-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/program-768.png b/docs/desktop-regression/screenshots/mobile-after/program-768.png
new file mode 100644
index 000000000..6eb899bf8
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/program-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/programs-320.png b/docs/desktop-regression/screenshots/mobile-after/programs-320.png
new file mode 100644
index 000000000..e64443230
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/programs-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/programs-390.png b/docs/desktop-regression/screenshots/mobile-after/programs-390.png
new file mode 100644
index 000000000..a5e1daef3
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/programs-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/programs-768.png b/docs/desktop-regression/screenshots/mobile-after/programs-768.png
new file mode 100644
index 000000000..d5d7f64fe
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/programs-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/project-320.png b/docs/desktop-regression/screenshots/mobile-after/project-320.png
new file mode 100644
index 000000000..270a2d0b3
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/project-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/project-390.png b/docs/desktop-regression/screenshots/mobile-after/project-390.png
new file mode 100644
index 000000000..28c978850
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/project-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/project-768.png b/docs/desktop-regression/screenshots/mobile-after/project-768.png
new file mode 100644
index 000000000..4b4882ef2
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/project-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/project-edit-320.png b/docs/desktop-regression/screenshots/mobile-after/project-edit-320.png
new file mode 100644
index 000000000..0f92f60e7
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/project-edit-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/project-edit-390.png b/docs/desktop-regression/screenshots/mobile-after/project-edit-390.png
new file mode 100644
index 000000000..6a9a84a90
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/project-edit-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/project-edit-768.png b/docs/desktop-regression/screenshots/mobile-after/project-edit-768.png
new file mode 100644
index 000000000..c0cb8e33e
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/project-edit-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/projects-320.png b/docs/desktop-regression/screenshots/mobile-after/projects-320.png
new file mode 100644
index 000000000..2bae40960
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/projects-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/projects-390.png b/docs/desktop-regression/screenshots/mobile-after/projects-390.png
new file mode 100644
index 000000000..e45c85ef0
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/projects-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/projects-768.png b/docs/desktop-regression/screenshots/mobile-after/projects-768.png
new file mode 100644
index 000000000..52815ac85
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/projects-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/vacancies-320.png b/docs/desktop-regression/screenshots/mobile-after/vacancies-320.png
new file mode 100644
index 000000000..fc5f46e06
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/vacancies-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/vacancies-390.png b/docs/desktop-regression/screenshots/mobile-after/vacancies-390.png
new file mode 100644
index 000000000..51d9cbf09
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/vacancies-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/vacancies-768.png b/docs/desktop-regression/screenshots/mobile-after/vacancies-768.png
new file mode 100644
index 000000000..62a2e140d
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/vacancies-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/vacancy-320.png b/docs/desktop-regression/screenshots/mobile-after/vacancy-320.png
new file mode 100644
index 000000000..4a550d06b
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/vacancy-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/vacancy-390.png b/docs/desktop-regression/screenshots/mobile-after/vacancy-390.png
new file mode 100644
index 000000000..d3ef7a9fb
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/vacancy-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-after/vacancy-768.png b/docs/desktop-regression/screenshots/mobile-after/vacancy-768.png
new file mode 100644
index 000000000..6945268a1
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-after/vacancy-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/course-320.png b/docs/desktop-regression/screenshots/mobile-before/course-320.png
new file mode 100644
index 000000000..a142af53d
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/course-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/course-390.png b/docs/desktop-regression/screenshots/mobile-before/course-390.png
new file mode 100644
index 000000000..febe2a0d9
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/course-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/course-768.png b/docs/desktop-regression/screenshots/mobile-before/course-768.png
new file mode 100644
index 000000000..a0d36aba7
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/course-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/courses-320.png b/docs/desktop-regression/screenshots/mobile-before/courses-320.png
new file mode 100644
index 000000000..c03bda60e
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/courses-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/courses-390.png b/docs/desktop-regression/screenshots/mobile-before/courses-390.png
new file mode 100644
index 000000000..9313fe831
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/courses-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/courses-768.png b/docs/desktop-regression/screenshots/mobile-before/courses-768.png
new file mode 100644
index 000000000..afd420a3d
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/courses-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/feed-320.png b/docs/desktop-regression/screenshots/mobile-before/feed-320.png
new file mode 100644
index 000000000..c408ae762
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/feed-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/feed-390.png b/docs/desktop-regression/screenshots/mobile-before/feed-390.png
new file mode 100644
index 000000000..bc1e6810b
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/feed-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/feed-768.png b/docs/desktop-regression/screenshots/mobile-before/feed-768.png
new file mode 100644
index 000000000..ca58289fd
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/feed-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/members-320.png b/docs/desktop-regression/screenshots/mobile-before/members-320.png
new file mode 100644
index 000000000..a2d5c15a9
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/members-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/members-390.png b/docs/desktop-regression/screenshots/mobile-before/members-390.png
new file mode 100644
index 000000000..006cc3b44
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/members-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/members-768.png b/docs/desktop-regression/screenshots/mobile-before/members-768.png
new file mode 100644
index 000000000..3f2af2700
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/members-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/my-projects-320.png b/docs/desktop-regression/screenshots/mobile-before/my-projects-320.png
new file mode 100644
index 000000000..0eb539b2f
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/my-projects-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/my-projects-390.png b/docs/desktop-regression/screenshots/mobile-before/my-projects-390.png
new file mode 100644
index 000000000..fdf04c57e
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/my-projects-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/my-projects-768.png b/docs/desktop-regression/screenshots/mobile-before/my-projects-768.png
new file mode 100644
index 000000000..e8b7c1c01
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/my-projects-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/profile-320.png b/docs/desktop-regression/screenshots/mobile-before/profile-320.png
new file mode 100644
index 000000000..6d986bb01
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/profile-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/profile-390.png b/docs/desktop-regression/screenshots/mobile-before/profile-390.png
new file mode 100644
index 000000000..3dc0eef00
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/profile-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/profile-768.png b/docs/desktop-regression/screenshots/mobile-before/profile-768.png
new file mode 100644
index 000000000..2792b9133
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/profile-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/profile-edit-320.png b/docs/desktop-regression/screenshots/mobile-before/profile-edit-320.png
new file mode 100644
index 000000000..30a3add05
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/profile-edit-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/profile-edit-390.png b/docs/desktop-regression/screenshots/mobile-before/profile-edit-390.png
new file mode 100644
index 000000000..eb3c0813f
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/profile-edit-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/profile-edit-768.png b/docs/desktop-regression/screenshots/mobile-before/profile-edit-768.png
new file mode 100644
index 000000000..ae37f77fb
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/profile-edit-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/program-320.png b/docs/desktop-regression/screenshots/mobile-before/program-320.png
new file mode 100644
index 000000000..d227b6fc7
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/program-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/program-390.png b/docs/desktop-regression/screenshots/mobile-before/program-390.png
new file mode 100644
index 000000000..ca42ebed2
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/program-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/program-768.png b/docs/desktop-regression/screenshots/mobile-before/program-768.png
new file mode 100644
index 000000000..6eb899bf8
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/program-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/programs-320.png b/docs/desktop-regression/screenshots/mobile-before/programs-320.png
new file mode 100644
index 000000000..e64443230
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/programs-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/programs-390.png b/docs/desktop-regression/screenshots/mobile-before/programs-390.png
new file mode 100644
index 000000000..a5e1daef3
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/programs-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/programs-768.png b/docs/desktop-regression/screenshots/mobile-before/programs-768.png
new file mode 100644
index 000000000..d5d7f64fe
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/programs-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/project-320.png b/docs/desktop-regression/screenshots/mobile-before/project-320.png
new file mode 100644
index 000000000..270a2d0b3
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/project-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/project-390.png b/docs/desktop-regression/screenshots/mobile-before/project-390.png
new file mode 100644
index 000000000..28c978850
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/project-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/project-768.png b/docs/desktop-regression/screenshots/mobile-before/project-768.png
new file mode 100644
index 000000000..4b4882ef2
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/project-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/project-edit-320.png b/docs/desktop-regression/screenshots/mobile-before/project-edit-320.png
new file mode 100644
index 000000000..0f92f60e7
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/project-edit-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/project-edit-390.png b/docs/desktop-regression/screenshots/mobile-before/project-edit-390.png
new file mode 100644
index 000000000..6a9a84a90
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/project-edit-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/project-edit-768.png b/docs/desktop-regression/screenshots/mobile-before/project-edit-768.png
new file mode 100644
index 000000000..c0cb8e33e
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/project-edit-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/projects-320.png b/docs/desktop-regression/screenshots/mobile-before/projects-320.png
new file mode 100644
index 000000000..2bae40960
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/projects-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/projects-390.png b/docs/desktop-regression/screenshots/mobile-before/projects-390.png
new file mode 100644
index 000000000..e45c85ef0
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/projects-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/projects-768.png b/docs/desktop-regression/screenshots/mobile-before/projects-768.png
new file mode 100644
index 000000000..52815ac85
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/projects-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/vacancies-320.png b/docs/desktop-regression/screenshots/mobile-before/vacancies-320.png
new file mode 100644
index 000000000..fc5f46e06
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/vacancies-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/vacancies-390.png b/docs/desktop-regression/screenshots/mobile-before/vacancies-390.png
new file mode 100644
index 000000000..51d9cbf09
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/vacancies-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/vacancies-768.png b/docs/desktop-regression/screenshots/mobile-before/vacancies-768.png
new file mode 100644
index 000000000..62a2e140d
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/vacancies-768.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/vacancy-320.png b/docs/desktop-regression/screenshots/mobile-before/vacancy-320.png
new file mode 100644
index 000000000..4a550d06b
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/vacancy-320.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/vacancy-390.png b/docs/desktop-regression/screenshots/mobile-before/vacancy-390.png
new file mode 100644
index 000000000..d3ef7a9fb
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/vacancy-390.png differ
diff --git a/docs/desktop-regression/screenshots/mobile-before/vacancy-768.png b/docs/desktop-regression/screenshots/mobile-before/vacancy-768.png
new file mode 100644
index 000000000..6945268a1
Binary files /dev/null and b/docs/desktop-regression/screenshots/mobile-before/vacancy-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/courses-320.png b/docs/desktop-regression/screenshots/states/courses-320.png
new file mode 100644
index 000000000..c03bda60e
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/courses-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/courses-390.png b/docs/desktop-regression/screenshots/states/courses-390.png
new file mode 100644
index 000000000..9313fe831
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/courses-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/courses-768.png b/docs/desktop-regression/screenshots/states/courses-768.png
new file mode 100644
index 000000000..afd420a3d
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/courses-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/disabled-action-320.png b/docs/desktop-regression/screenshots/states/disabled-action-320.png
new file mode 100644
index 000000000..f92508267
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/disabled-action-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/disabled-action-390.png b/docs/desktop-regression/screenshots/states/disabled-action-390.png
new file mode 100644
index 000000000..4e9054b07
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/disabled-action-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/disabled-action-768.png b/docs/desktop-regression/screenshots/states/disabled-action-768.png
new file mode 100644
index 000000000..a82eea418
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/disabled-action-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/disabled-filter-320.png b/docs/desktop-regression/screenshots/states/disabled-filter-320.png
new file mode 100644
index 000000000..9c2c2d7d1
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/disabled-filter-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/disabled-filter-390.png b/docs/desktop-regression/screenshots/states/disabled-filter-390.png
new file mode 100644
index 000000000..184878e47
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/disabled-filter-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/disabled-filter-768.png b/docs/desktop-regression/screenshots/states/disabled-filter-768.png
new file mode 100644
index 000000000..567f3eb2e
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/disabled-filter-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/empty-320.png b/docs/desktop-regression/screenshots/states/empty-320.png
new file mode 100644
index 000000000..93d132e62
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/empty-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/empty-390.png b/docs/desktop-regression/screenshots/states/empty-390.png
new file mode 100644
index 000000000..b593e4018
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/empty-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/empty-768.png b/docs/desktop-regression/screenshots/states/empty-768.png
new file mode 100644
index 000000000..f0c4cb271
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/empty-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/error-320.png b/docs/desktop-regression/screenshots/states/error-320.png
new file mode 100644
index 000000000..cdba1f904
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/error-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/error-390.png b/docs/desktop-regression/screenshots/states/error-390.png
new file mode 100644
index 000000000..052424d60
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/error-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/error-768.png b/docs/desktop-regression/screenshots/states/error-768.png
new file mode 100644
index 000000000..56b5e3444
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/error-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/loading-action-320.png b/docs/desktop-regression/screenshots/states/loading-action-320.png
new file mode 100644
index 000000000..9b57305f1
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/loading-action-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/loading-action-390.png b/docs/desktop-regression/screenshots/states/loading-action-390.png
new file mode 100644
index 000000000..ec4a061d9
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/loading-action-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/loading-action-768.png b/docs/desktop-regression/screenshots/states/loading-action-768.png
new file mode 100644
index 000000000..6e10d31f9
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/loading-action-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/loading-page-320.png b/docs/desktop-regression/screenshots/states/loading-page-320.png
new file mode 100644
index 000000000..c386bf550
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/loading-page-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/loading-page-390.png b/docs/desktop-regression/screenshots/states/loading-page-390.png
new file mode 100644
index 000000000..a77ddf8e8
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/loading-page-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/loading-page-768.png b/docs/desktop-regression/screenshots/states/loading-page-768.png
new file mode 100644
index 000000000..ae67594c0
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/loading-page-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/onboarding-0-320.png b/docs/desktop-regression/screenshots/states/onboarding-0-320.png
new file mode 100644
index 000000000..36dd2eeaa
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/onboarding-0-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/onboarding-0-390.png b/docs/desktop-regression/screenshots/states/onboarding-0-390.png
new file mode 100644
index 000000000..3b81d2e46
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/onboarding-0-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/onboarding-0-768.png b/docs/desktop-regression/screenshots/states/onboarding-0-768.png
new file mode 100644
index 000000000..4418d4954
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/onboarding-0-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/onboarding-1-320.png b/docs/desktop-regression/screenshots/states/onboarding-1-320.png
new file mode 100644
index 000000000..f0e2ed53a
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/onboarding-1-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/onboarding-1-390.png b/docs/desktop-regression/screenshots/states/onboarding-1-390.png
new file mode 100644
index 000000000..cc03fb3c6
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/onboarding-1-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/onboarding-1-768.png b/docs/desktop-regression/screenshots/states/onboarding-1-768.png
new file mode 100644
index 000000000..ef3fa50cc
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/onboarding-1-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/profile-320.png b/docs/desktop-regression/screenshots/states/profile-320.png
new file mode 100644
index 000000000..3007d338d
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/profile-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/profile-390.png b/docs/desktop-regression/screenshots/states/profile-390.png
new file mode 100644
index 000000000..23a1958f6
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/profile-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/profile-768.png b/docs/desktop-regression/screenshots/states/profile-768.png
new file mode 100644
index 000000000..696de1882
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/profile-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/profile-edit-320.png b/docs/desktop-regression/screenshots/states/profile-edit-320.png
new file mode 100644
index 000000000..3c7c46269
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/profile-edit-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/profile-edit-390.png b/docs/desktop-regression/screenshots/states/profile-edit-390.png
new file mode 100644
index 000000000..0dde9893b
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/profile-edit-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/profile-edit-768.png b/docs/desktop-regression/screenshots/states/profile-edit-768.png
new file mode 100644
index 000000000..a3fa20e45
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/profile-edit-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/programs-320.png b/docs/desktop-regression/screenshots/states/programs-320.png
new file mode 100644
index 000000000..d7f61925a
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/programs-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/programs-390.png b/docs/desktop-regression/screenshots/states/programs-390.png
new file mode 100644
index 000000000..d8f937994
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/programs-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/programs-768.png b/docs/desktop-regression/screenshots/states/programs-768.png
new file mode 100644
index 000000000..64809084b
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/programs-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/projects-320.png b/docs/desktop-regression/screenshots/states/projects-320.png
new file mode 100644
index 000000000..3dcc89602
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/projects-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/projects-390.png b/docs/desktop-regression/screenshots/states/projects-390.png
new file mode 100644
index 000000000..7dd67c6df
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/projects-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/projects-768.png b/docs/desktop-regression/screenshots/states/projects-768.png
new file mode 100644
index 000000000..bcc45f8d2
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/projects-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/vacancies-320.png b/docs/desktop-regression/screenshots/states/vacancies-320.png
new file mode 100644
index 000000000..3f179ca86
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/vacancies-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/vacancies-390.png b/docs/desktop-regression/screenshots/states/vacancies-390.png
new file mode 100644
index 000000000..a5e64f193
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/vacancies-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/vacancies-768.png b/docs/desktop-regression/screenshots/states/vacancies-768.png
new file mode 100644
index 000000000..5a79d747c
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/vacancies-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/validation-onboarding-320.png b/docs/desktop-regression/screenshots/states/validation-onboarding-320.png
new file mode 100644
index 000000000..9b33f1f33
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/validation-onboarding-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/validation-onboarding-390.png b/docs/desktop-regression/screenshots/states/validation-onboarding-390.png
new file mode 100644
index 000000000..66bf115ec
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/validation-onboarding-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/validation-onboarding-768.png b/docs/desktop-regression/screenshots/states/validation-onboarding-768.png
new file mode 100644
index 000000000..6a197ba8a
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/validation-onboarding-768.png differ
diff --git a/docs/desktop-regression/screenshots/states/validation-register-320.png b/docs/desktop-regression/screenshots/states/validation-register-320.png
new file mode 100644
index 000000000..9d0beb34b
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/validation-register-320.png differ
diff --git a/docs/desktop-regression/screenshots/states/validation-register-390.png b/docs/desktop-regression/screenshots/states/validation-register-390.png
new file mode 100644
index 000000000..50909334f
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/validation-register-390.png differ
diff --git a/docs/desktop-regression/screenshots/states/validation-register-768.png b/docs/desktop-regression/screenshots/states/validation-register-768.png
new file mode 100644
index 000000000..0d5a78f7c
Binary files /dev/null and b/docs/desktop-regression/screenshots/states/validation-register-768.png differ
diff --git a/docs/desktop-regression/serve.cjs b/docs/desktop-regression/serve.cjs
new file mode 100644
index 000000000..acb32077c
--- /dev/null
+++ b/docs/desktop-regression/serve.cjs
@@ -0,0 +1,37 @@
+/** @format */
+
+const http = require("node:http");
+const fs = require("node:fs");
+const path = require("node:path");
+let root = path.resolve(process.argv[2]);
+if (fs.existsSync(path.join(root, "browser/index.html"))) root = path.join(root, "browser");
+const port = Number(process.argv[3]);
+const types = {
+ ".html": "text/html",
+ ".js": "text/javascript",
+ ".css": "text/css",
+ ".svg": "image/svg+xml",
+ ".png": "image/png",
+ ".jpg": "image/jpeg",
+ ".woff2": "font/woff2",
+ ".woff": "font/woff",
+ ".json": "application/json",
+ ".md": "text/plain; charset=utf-8",
+};
+http
+ .createServer((request, response) => {
+ let file = path.resolve(
+ root,
+ "." + decodeURIComponent(new URL(request.url, "http://localhost").pathname),
+ );
+ if (!file.startsWith(root + path.sep)) return response.writeHead(403).end();
+ if (!fs.existsSync(file) || fs.statSync(file).isDirectory())
+ file = path.join(root, "index.html");
+ if (!fs.existsSync(file)) return response.writeHead(404).end("Not found");
+ response.writeHead(200, {
+ "Content-Type": types[path.extname(file)] || "application/octet-stream",
+ "Cache-Control": "no-store",
+ });
+ fs.createReadStream(file).pipe(response);
+ })
+ .listen(port, "127.0.0.1", () => console.log(`Preview ${port}: ${root}`));
diff --git a/docs/desktop-regression/source-files.json b/docs/desktop-regression/source-files.json
new file mode 100644
index 000000000..24da40995
--- /dev/null
+++ b/docs/desktop-regression/source-files.json
@@ -0,0 +1,139 @@
+[
+ "projects/social_platform/src/app/ui/pages/auth/auth.component.scss",
+ "projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.scss",
+ "projects/social_platform/src/app/ui/pages/auth/login/login.component.scss",
+ "projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.scss",
+ "projects/social_platform/src/app/ui/pages/courses/lesson/shared/file-task/file-task.component.scss",
+ "projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.scss",
+ "projects/social_platform/src/app/ui/pages/courses/lesson/shared/video-task/info-task.component.scss",
+ "projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.scss",
+ "projects/social_platform/src/app/ui/pages/courses/list/course/course.component.html",
+ "projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss",
+ "projects/social_platform/src/app/ui/pages/courses/list/course/course.component.ts",
+ "projects/social_platform/src/app/ui/pages/courses/list/list.component.html",
+ "projects/social_platform/src/app/ui/pages/courses/list/list.component.ts",
+ "projects/social_platform/src/app/ui/pages/error/error-code/error-code.component.scss",
+ "projects/social_platform/src/app/ui/pages/feed/feed.component.html",
+ "projects/social_platform/src/app/ui/pages/feed/feed.component.ts",
+ "projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.html",
+ "projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.ts",
+ "projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss",
+ "projects/social_platform/src/app/ui/pages/members/member-filters-dialog/member-filters-dialog.component.scss",
+ "projects/social_platform/src/app/ui/pages/members/member-statistics-card/member-statistics-card.component.scss",
+ "projects/social_platform/src/app/ui/pages/members/members-filters/members-filters.component.scss",
+ "projects/social_platform/src/app/ui/pages/members/members.component.html",
+ "projects/social_platform/src/app/ui/pages/members/members.component.scss",
+ "projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss",
+ "projects/social_platform/src/app/ui/pages/office/office.component.scss",
+ "projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/detail/profile-news/profile-news.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/edit/components/profile-achievements-step/profile-achievements-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/edit/components/profile-education-step/profile-education-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/edit/components/profile-experience-step/profile-experience-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/edit/components/profile-skills-step/profile-skills-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/edit/edit.component.html",
+ "projects/social_platform/src/app/ui/pages/profile/edit/edit.component.scss",
+ "projects/social_platform/src/app/ui/pages/profile/edit/edit.component.ts",
+ "projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.scss",
+ "projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.scss",
+ "projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss",
+ "projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/boolean-criterion/boolean-criterion.component.scss",
+ "projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.scss",
+ "projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.scss",
+ "projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.html",
+ "projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.scss",
+ "projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.ts",
+ "projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.html",
+ "projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts",
+ "projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-left-side/projects-left-side.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/detail/team/team.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/detail/work-section/work-section.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.html",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.ts",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/edit/edit.component.html",
+ "projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/project-activity-card/project-activity-card.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/projects-activity-placement.spec.ts",
+ "projects/social_platform/src/app/ui/pages/projects/projects.component.html",
+ "projects/social_platform/src/app/ui/pages/projects/projects.component.scss",
+ "projects/social_platform/src/app/ui/pages/projects/projects.component.ts",
+ "projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss",
+ "projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss",
+ "projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss",
+ "projects/social_platform/src/app/ui/pages/vacancies/list/list.component.html",
+ "projects/social_platform/src/app/ui/pages/vacancies/list/list.component.ts",
+ "projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss",
+ "projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss",
+ "projects/social_platform/src/app/ui/primitives/avatar/avatar.component.html",
+ "projects/social_platform/src/app/ui/primitives/avatar/avatar.component.scss",
+ "projects/social_platform/src/app/ui/primitives/avatar/avatar.component.ts",
+ "projects/social_platform/src/app/ui/primitives/bar/bar.component.html",
+ "projects/social_platform/src/app/ui/primitives/bar/bar.component.scss",
+ "projects/social_platform/src/app/ui/primitives/bar/bar.component.ts",
+ "projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss",
+ "projects/social_platform/src/app/ui/primitives/dropdown/dropdown.component.scss",
+ "projects/social_platform/src/app/ui/primitives/file-item/file-item.component.scss",
+ "projects/social_platform/src/app/ui/primitives/input/input.component.scss",
+ "projects/social_platform/src/app/ui/primitives/modal/modal.component.scss",
+ "projects/social_platform/src/app/ui/primitives/search/search.component.scss",
+ "projects/social_platform/src/app/ui/primitives/select/select.component.scss",
+ "projects/social_platform/src/app/ui/primitives/switch/switch.component.scss",
+ "projects/social_platform/src/app/ui/primitives/tag/tag.component.scss",
+ "projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss",
+ "projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.scss",
+ "projects/social_platform/src/app/ui/widgets/cookie-consent/cookie-consent.component.scss",
+ "projects/social_platform/src/app/ui/widgets/detail/detail.component.html",
+ "projects/social_platform/src/app/ui/widgets/detail/detail.component.scss",
+ "projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.scss",
+ "projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss",
+ "projects/social_platform/src/app/ui/widgets/news-card/feed-news-modal/feed-news-modal.component.scss",
+ "projects/social_platform/src/app/ui/widgets/news-card/feed-news-preview/feed-news-preview.component.scss",
+ "projects/social_platform/src/app/ui/widgets/news-card/news-card.component.scss",
+ "projects/social_platform/src/app/ui/widgets/news-form/news-form.component.scss",
+ "projects/social_platform/src/app/ui/widgets/project-invite/project-invite-dialog.component.scss",
+ "projects/social_platform/src/app/ui/widgets/project-invite/project-invite-role-input.component.scss",
+ "projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss",
+ "projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.scss",
+ "projects/social_platform/src/app/ui/widgets/region-select/region-select.component.scss",
+ "projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.scss",
+ "projects/social_platform/src/app/ui/widgets/vacancy-created-dialog/vacancy-created-dialog.component.scss",
+ "projects/social_platform/src/app/ui/widgets/vacancy-filter/vacancy-filter.component.scss",
+ "projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.scss",
+ "projects/social_platform/src/app/ui/widgets/vacancy-status/vacancy-status.component.scss",
+ "projects/social_platform/src/styles.scss",
+ "projects/social_platform/src/styles/_course-task.scss",
+ "projects/social_platform/src/styles/_feed-card.scss",
+ "projects/social_platform/src/styles/_platform-responsive.scss",
+ "projects/social_platform/src/styles/_typography.scss",
+ "projects/social_platform/src/styles/_ui-system.scss",
+ "projects/social_platform/src/styles/components/_vacancy-ui.scss",
+ "projects/ui/src/lib/components/layout/page-header/page-header.component.scss",
+ "projects/ui/src/lib/components/layout/page-header/page-header.component.ts",
+ "projects/ui/src/lib/components/layout/profile-control-panel/profile-control-panel.component.html",
+ "projects/ui/src/lib/components/layout/profile-control-panel/profile-control-panel.component.scss",
+ "projects/ui/src/lib/components/layout/profile-control-panel/profile-control-panel.component.ts",
+ "projects/ui/src/lib/components/primitives/avatar/avatar.component.scss",
+ "projects/ui/src/lib/components/primitives/back/back.component.scss",
+ "projects/ui/src/lib/components/primitives/badge/badge.component.scss",
+ "projects/ui/src/lib/components/primitives/button/button.component.html",
+ "projects/ui/src/lib/components/primitives/button/button.component.scss",
+ "projects/ui/src/lib/components/primitives/button/button.component.ts",
+ "projects/ui/src/lib/components/primitives/icon/icon.component.html",
+ "projects/ui/src/lib/components/primitives/icon/icon.component.scss",
+ "projects/ui/src/lib/components/primitives/icon/icon.component.ts",
+ "projects/ui/src/lib/components/primitives/loader/loader.component.scss",
+ "projects/ui/src/lib/components/primitives/tabs/tabs.component.scss",
+ "projects/ui/src/lib/services/desktop-layout.service.ts",
+ "projects/ui/src/public-api.ts"
+]
diff --git a/docs/desktop-regression/states.cjs b/docs/desktop-regression/states.cjs
new file mode 100644
index 000000000..a89459400
--- /dev/null
+++ b/docs/desktop-regression/states.cjs
@@ -0,0 +1,232 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch, assertViewport } = require("../responsive/browser-harness.cjs");
+const fixtures = require("../responsive/fixtures.cjs");
+
+const directory = path.join(__dirname, "screenshots", "states");
+fs.mkdirSync(directory, { recursive: true });
+const rows = [];
+const widths = [320, 390, 768];
+const sections = [
+ ["projects", "/office/projects/all", "app-info-card"],
+ ["vacancies", "/office/vacancies/all", "app-project-vacancy-card"],
+ ["programs", "/office/program/all", "app-program-card"],
+ ["courses", "/office/courses/all", "app-course"],
+ ["profile", "/office/profile/1", "app-detail"],
+ ["profile-edit", "/office/profile/edit?editingStep=main", "app-page-header"],
+ [
+ "onboarding-0",
+ "/office/onboarding/stage-0",
+ "app-stage-zero .page__form input:not([type=file])",
+ ],
+ ["onboarding-1", "/office/onboarding/stage-1", "app-stage-one app-autocomplete-input"],
+];
+
+async function goto(page, route, settled = true) {
+ await page.goto("http://127.0.0.1:4360" + route);
+ if (settled) await page.waitForLoadState("networkidle");
+}
+
+async function capture(harness, name, width, extra = {}) {
+ const measurement = await assertViewport(harness.page);
+ const expectedErrors = extra.injectedHttp500
+ ? harness.errors.filter(
+ message =>
+ /Failed to load resource.*500/.test(message) ||
+ /\[ERROR\] \[HTTP\] GET https:\/\/(?:api|dev)\.procollab\.ru\/programs\/1\/manager-overview\/ 500 /.test(
+ message,
+ ),
+ )
+ : [];
+ assert.deepEqual(
+ harness.errors.filter(message => !expectedErrors.includes(message)),
+ [],
+ );
+ const screenshot = `screenshots/states/${name}-${width}.png`;
+ await harness.page.screenshot({ path: path.join(__dirname, screenshot), fullPage: true });
+ rows.push({ name, width, passed: true, ...measurement, screenshot, expectedErrors, ...extra });
+ console.log(JSON.stringify({ name, width, passed: true }));
+}
+
+async function state(width, name, action) {
+ const harness = await launch(width, { isMobile: width < 750, hasTouch: width < 750 });
+ harness.page.setDefaultTimeout(8000);
+ try {
+ await action(harness);
+ } finally {
+ await harness.browser.close();
+ }
+}
+
+(async () => {
+ for (const width of widths) {
+ const harness = await launch(width, { isMobile: width < 750, hasTouch: width < 750 });
+ try {
+ for (const [name, route, content] of sections) {
+ harness.errors.length = 0;
+ await goto(harness.page, route);
+ await harness.page.locator(content).first().waitFor({ state: "visible" });
+ await capture(harness, name, width, { category: "section" });
+ }
+ } finally {
+ await harness.browser.close();
+ }
+
+ await state(width, "loading-page", async h => {
+ let release;
+ const pending = new Promise(resolve => {
+ release = resolve;
+ });
+ await h.context.route("**/programs/1/manager-overview/**", async route => {
+ await pending;
+ const url = new URL(route.request().url());
+ await route.fulfill({ json: fixtures.response(url.pathname, "GET", url.searchParams) });
+ });
+ try {
+ await goto(h.page, "/office/program/1/analytics", false);
+ await h.page.getByTestId("analytics-loading").waitFor();
+ await capture(h, "loading-page", width, { category: "loading" });
+ } finally {
+ release();
+ }
+ await h.page.getByTestId("analytics-loading").waitFor({ state: "hidden" });
+ });
+
+ await state(width, "loading-action", async h => {
+ await goto(h.page, "/office/courses/1/lesson/1");
+ await h.page.locator("app-write-task textarea").fill("Ответ для финальной проверки UI Kit");
+ let release;
+ const pending = new Promise(resolve => {
+ release = resolve;
+ });
+ let submissions = 0;
+ await h.context.route("**/courses/tasks/1/answer/", async route => {
+ submissions++;
+ await pending;
+ const url = new URL(route.request().url());
+ await route.fulfill({ json: fixtures.response(url.pathname, "POST", url.searchParams) });
+ });
+ try {
+ const button = h.page.getByRole("button", { name: "завершить урок", exact: true });
+ await button.click();
+ await h.page.locator("app-button app-loader").waitFor();
+ assert.equal(await button.isDisabled(), true);
+ assert.equal(await button.getAttribute("aria-busy"), "true");
+ await button.evaluate(element => element.click());
+ assert.equal(submissions, 1, "Loading must prevent duplicate submission");
+ await capture(h, "loading-action", width, { category: "loading", submissions });
+ } finally {
+ release();
+ }
+ await h.page.locator("app-complete").waitFor();
+ });
+
+ await state(width, "empty", async h => {
+ await h.context.route(
+ url => /\/vacancies\/$/.test(url.pathname),
+ route => route.fulfill({ json: { count: 0, results: [], next: null, previous: null } }),
+ );
+ await goto(h.page, "/office/vacancies/all");
+ await h.page.locator("app-state").getByText("Вакансии не найдены", { exact: true }).waitFor();
+ await capture(h, "empty", width, { category: "empty" });
+ });
+
+ await state(width, "error", async h => {
+ let failing = true;
+ let attempts = 0;
+ await h.context.route("**/programs/1/manager-overview/**", async route => {
+ attempts++;
+ if (failing) return route.fulfill({ status: 500, json: { detail: "Injected QA failure" } });
+ const url = new URL(route.request().url());
+ return route.fulfill({ json: fixtures.response(url.pathname, "GET", url.searchParams) });
+ });
+ await goto(h.page, "/office/program/1/analytics");
+ await h.page.getByTestId("analytics-error").waitFor({ timeout: 60000 });
+ assert.equal(await h.page.getByTestId("analytics-error").getAttribute("role"), "alert");
+ await capture(h, "error", width, { category: "error", injectedHttp500: true });
+ failing = false;
+ await h.page.getByRole("button", { name: "Повторить", exact: true }).click();
+ await h.page.getByTestId("analytics-error").waitFor({ state: "hidden" });
+ await h.page.locator(".summary-card").first().waitFor();
+ assert.ok(attempts >= 2, "Error retry must reload data");
+ await assertViewport(h.page);
+ rows.at(-1).retryPassed = true;
+ });
+
+ await state(width, "disabled-action", async h => {
+ await goto(h.page, "/office/courses/1/lesson/1");
+ const button = h.page.getByRole("button", { name: "завершить урок", exact: true });
+ assert.equal(await button.isDisabled(), true);
+ const before = h.requests.filter(request => request.method !== "GET").length;
+ await button.evaluate(element => element.click());
+ assert.equal(h.requests.filter(request => request.method !== "GET").length, before);
+ assert.equal(
+ await button.evaluate(element => {
+ element.focus();
+ return document.activeElement !== element;
+ }),
+ true,
+ );
+ await capture(h, "disabled-action", width, { category: "disabled" });
+ });
+
+ await state(width, "disabled-filter", async h => {
+ await goto(h.page, "/office/feed");
+ const button = h.page.getByRole("button", { name: /образование/ });
+ assert.equal(await button.isDisabled(), true);
+ const before = h.page.url();
+ await button.evaluate(element => element.click());
+ assert.equal(h.page.url(), before);
+ await capture(h, "disabled-filter", width, { category: "disabled" });
+ });
+
+ await state(width, "validation-register", async h => {
+ await goto(h.page, "/auth/register");
+ if (width >= 1000) {
+ const register = await h.page.locator(".register").boundingBox();
+ assert.ok(register.x >= 199, "Registration must retain the desktop auth gutter");
+ }
+ for (const checkbox of await h.page.locator("app-checkbox .field").all())
+ await checkbox.click();
+ await h.page.getByRole("button", { name: "зарегистрироваться", exact: true }).click();
+ await h.page.locator(".error").first().waitFor();
+ assert.equal(
+ h.requests.some(
+ request => request.method === "POST" && /\/auth\/users\/$/.test(request.path),
+ ),
+ false,
+ );
+ await capture(h, "validation-register", width, { category: "validation" });
+ });
+
+ const avatar = fixtures.user.avatar;
+ fixtures.user.avatar = null;
+ try {
+ await state(width, "validation-onboarding", async h => {
+ await goto(h.page, "/office/onboarding/stage-0");
+ await h.page.getByRole("button", { name: "продолжить", exact: true }).click();
+ await h.page.locator(".error").first().waitFor();
+ assert.equal(h.page.url().includes("stage-0"), true);
+ assert.equal(
+ h.requests.some(request => request.method === "PATCH"),
+ false,
+ );
+ await capture(h, "validation-onboarding", width, { category: "validation" });
+ });
+ } finally {
+ fixtures.user.avatar = avatar;
+ }
+ }
+ assert.equal(rows.length, 48);
+ fs.writeFileSync(
+ path.join(__dirname, "states.json"),
+ JSON.stringify({ widths, rows }, null, 2) + "\n",
+ );
+ console.log(`${rows.length} UI state checks passed`);
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/desktop-regression/states.json b/docs/desktop-regression/states.json
new file mode 100644
index 000000000..f994a9249
--- /dev/null
+++ b/docs/desktop-regression/states.json
@@ -0,0 +1,2330 @@
+{
+ "widths": [320, 390, 768],
+ "rows": [
+ {
+ "name": "projects",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/projects/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-projects-filter",
+ "app-select",
+ "app-dropdown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-projects-filter",
+ "app-select"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\nФильтр\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nПроект для проверки адаптива\n\nОткрыть\n\nфильтры\n\nсбросить\nсфера проекта",
+ "screenshot": "screenshots/states/projects-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "vacancies",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело",
+ "screenshot": "screenshots/states/vacancies-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "programs",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "screenshot": "screenshots/states/programs-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "courses",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение",
+ "screenshot": "screenshots/states/courses-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвание",
+ "screenshot": "screenshots/states/profile-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile-edit",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон",
+ "screenshot": "screenshots/states/profile-edit-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-0",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nРегион*\n\nОбразование\n\nУровень образования\nВысшее образова",
+ "screenshot": "screenshots/states/onboarding-0-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-1",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group"
+ ],
+ "text": "1\n2\n3\n4\nКем хотите работать?\nзакончить регистрацию позже\nпродолжить\nпоиск по библиотеке\nбиблиотека\nРазработчик",
+ "screenshot": "screenshots/states/onboarding-1-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "loading-page",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nЗагружаем аналитику программы…",
+ "screenshot": "screenshots/states/loading-page-320.png",
+ "expectedErrors": [],
+ "category": "loading"
+ },
+ {
+ "name": "loading-action",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n35 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/loading-action-320.png",
+ "expectedErrors": [],
+ "category": "loading",
+ "submissions": 1
+ },
+ {
+ "name": "empty",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nВакансии не найдены\n\nПопробуйте изменить запрос или сбросить фильтры.\n\nСбросить фильтры\nфильтры\nмои отклики",
+ "screenshot": "screenshots/states/empty-320.png",
+ "expectedErrors": [],
+ "category": "empty"
+ },
+ {
+ "name": "error",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nАналитика недоступна\n\nНе удалось загрузить аналитику. ",
+ "screenshot": "screenshots/states/error-320.png",
+ "expectedErrors": [
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:30:42.177] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 67ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:30:44.192] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 8ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:30:48.202] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 4ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:30:56.209] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 4ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\""
+ ],
+ "category": "error",
+ "injectedHttp500": true,
+ "retryPassed": true
+ },
+ {
+ "name": "disabled-action",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n0 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/disabled-action-320.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "disabled-filter",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-state",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-state"
+ ],
+ "text": "Новости\nвсе новости\n0\nновости проектов\n0\nсвежие вакансии\n0\nновости сообщества\n0\nновости программ\n0\nобразование\n0\n\nв данном разделе пока нет новостей",
+ "screenshot": "screenshots/states/disabled-filter-320.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "validation-register",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/auth/register",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button",
+ "app-modal",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button"
+ ],
+ "text": "имя\nфамилия\nдата рождения\nпочта\nпароль\nповторите пароль\nОбязательное поле\nя прочитал соглашение и даю согласие на обработку персональных данных\nнажимая на кнопку подтверждаете, что вам больше 14 лет\nзарегистрироваться\n\nесли есть аккаунт? - войдите",
+ "screenshot": "screenshots/states/validation-register-320.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "validation-onboarding",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nВыберите фото для профиля\nРегион*\n\nОбразование\n\nУровень о",
+ "screenshot": "screenshots/states/validation-onboarding-320.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "projects",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/projects/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-projects-filter",
+ "app-select",
+ "app-dropdown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-projects-filter",
+ "app-select"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\nФильтр\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nПроект для проверки адаптива\n\nОткрыть\n\nфильтры\n\nсбросить\nсфера проекта",
+ "screenshot": "screenshots/states/projects-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "vacancies",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело",
+ "screenshot": "screenshots/states/vacancies-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "programs",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "screenshot": "screenshots/states/programs-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "courses",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение",
+ "screenshot": "screenshots/states/courses-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвание",
+ "screenshot": "screenshots/states/profile-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile-edit",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон",
+ "screenshot": "screenshots/states/profile-edit-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-0",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nРегион*\n\nОбразование\n\nУровень образования\nВысшее образова",
+ "screenshot": "screenshots/states/onboarding-0-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-1",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group"
+ ],
+ "text": "1\n2\n3\n4\nКем хотите работать?\nзакончить регистрацию позже\nпродолжить\nпоиск по библиотеке\nбиблиотека\nРазработчик",
+ "screenshot": "screenshots/states/onboarding-1-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "loading-page",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nЗагружаем аналитику программы…",
+ "screenshot": "screenshots/states/loading-page-390.png",
+ "expectedErrors": [],
+ "category": "loading"
+ },
+ {
+ "name": "loading-action",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n35 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/loading-action-390.png",
+ "expectedErrors": [],
+ "category": "loading",
+ "submissions": 1
+ },
+ {
+ "name": "empty",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nВакансии не найдены\n\nПопробуйте изменить запрос или сбросить фильтры.\n\nСбросить фильтры\nфильтры\nмои отклики",
+ "screenshot": "screenshots/states/empty-390.png",
+ "expectedErrors": [],
+ "category": "empty"
+ },
+ {
+ "name": "error",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nАналитика недоступна\n\nНе удалось загрузить аналитику. ",
+ "screenshot": "screenshots/states/error-390.png",
+ "expectedErrors": [
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:31:22.860] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 41ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:31:24.869] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:31:28.877] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 4ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:31:36.882] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\""
+ ],
+ "category": "error",
+ "injectedHttp500": true,
+ "retryPassed": true
+ },
+ {
+ "name": "disabled-action",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n0 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/disabled-action-390.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "disabled-filter",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-state",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-state"
+ ],
+ "text": "Новости\nвсе новости\n0\nновости проектов\n0\nсвежие вакансии\n0\nновости сообщества\n0\nновости программ\n0\nобразование\n0\n\nв данном разделе пока нет новостей",
+ "screenshot": "screenshots/states/disabled-filter-390.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "validation-register",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/auth/register",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button",
+ "app-modal",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button"
+ ],
+ "text": "имя\nфамилия\nдата рождения\nпочта\nпароль\nповторите пароль\nОбязательное поле\nя прочитал соглашение и даю согласие на обработку персональных данных\nнажимая на кнопку подтверждаете, что вам больше 14 лет\nзарегистрироваться\n\nесли есть аккаунт? - войдите",
+ "screenshot": "screenshots/states/validation-register-390.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "validation-onboarding",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nВыберите фото для профиля\nРегион*\n\nОбразование\n\nУровень о",
+ "screenshot": "screenshots/states/validation-onboarding-390.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "projects",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/projects/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-projects-filter",
+ "app-select",
+ "app-dropdown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-projects-filter",
+ "app-select"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\nФильтр\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nПроект для проверки адаптива\n\nОткрыть\n\nфильтры\n\nсбросить\nсфера проекта",
+ "screenshot": "screenshots/states/projects-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "vacancies",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело",
+ "screenshot": "screenshots/states/vacancies-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "programs",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "screenshot": "screenshots/states/programs-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "courses",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение",
+ "screenshot": "screenshots/states/courses-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвание",
+ "screenshot": "screenshots/states/profile-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile-edit",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон",
+ "screenshot": "screenshots/states/profile-edit-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-0",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nРегион*\n\nОбразование\n\nУровень образования\nВысшее образова",
+ "screenshot": "screenshots/states/onboarding-0-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-1",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group"
+ ],
+ "text": "1\n2\n3\n4\nКем хотите работать?\nзакончить регистрацию позже\nпродолжить\nпоиск по библиотеке\nбиблиотека\nРазработчик",
+ "screenshot": "screenshots/states/onboarding-1-768.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "loading-page",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nЗагружаем аналитику программы…",
+ "screenshot": "screenshots/states/loading-page-768.png",
+ "expectedErrors": [],
+ "category": "loading"
+ },
+ {
+ "name": "loading-action",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n35 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/loading-action-768.png",
+ "expectedErrors": [],
+ "category": "loading",
+ "submissions": 1
+ },
+ {
+ "name": "empty",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nВакансии не найдены\n\nПопробуйте изменить запрос или сбросить фильтры.\n\nСбросить фильтры\nфильтры\nмои отклики",
+ "screenshot": "screenshots/states/empty-768.png",
+ "expectedErrors": [],
+ "category": "empty"
+ },
+ {
+ "name": "error",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nАналитика недоступна\n\nНе удалось загрузить аналитику. ",
+ "screenshot": "screenshots/states/error-768.png",
+ "expectedErrors": [
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:32:02.687] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 49ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:32:04.697] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:32:08.703] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 2ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[15:32:16.712] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 4ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\""
+ ],
+ "category": "error",
+ "injectedHttp500": true,
+ "retryPassed": true
+ },
+ {
+ "name": "disabled-action",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n0 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/disabled-action-768.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "disabled-filter",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-state",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-state"
+ ],
+ "text": "Новости\nвсе новости\n0\nновости проектов\n0\nсвежие вакансии\n0\nновости сообщества\n0\nновости программ\n0\nобразование\n0\n\nв данном разделе пока нет новостей",
+ "screenshot": "screenshots/states/disabled-filter-768.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "validation-register",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/auth/register",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button",
+ "app-modal",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button"
+ ],
+ "text": "имя\nфамилия\nдата рождения\nпочта\nпароль\nповторите пароль\nОбязательное поле\nя прочитал соглашение и даю согласие на обработку персональных данных\nнажимая на кнопку подтверждаете, что вам больше 14 лет\nзарегистрироваться\n\nесли есть аккаунт? - войдите",
+ "screenshot": "screenshots/states/validation-register-768.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "validation-onboarding",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nВыберите фото для профиля\nРегион*\n\nОбразование\n\nУровень о",
+ "screenshot": "screenshots/states/validation-onboarding-768.png",
+ "expectedErrors": [],
+ "category": "validation"
+ }
+ ]
+}
diff --git a/docs/desktop-regression/states.log b/docs/desktop-regression/states.log
new file mode 100644
index 000000000..3a8b9e447
--- /dev/null
+++ b/docs/desktop-regression/states.log
@@ -0,0 +1,69 @@
+{"name":"projects","width":320,"passed":true}
+{"name":"vacancies","width":320,"passed":true}
+{"name":"programs","width":320,"passed":true}
+{"name":"courses","width":320,"passed":true}
+{"name":"profile","width":320,"passed":true}
+{"name":"profile-edit","width":320,"passed":true}
+{"name":"onboarding-0","width":320,"passed":true}
+{"name":"onboarding-1","width":320,"passed":true}
+{"name":"loading-page","width":320,"passed":true}
+{"name":"loading-action","width":320,"passed":true}
+{"name":"empty","width":320,"passed":true}
+{"name":"error","width":320,"passed":true}
+{"name":"disabled-action","width":320,"passed":true}
+{"name":"disabled-filter","width":320,"passed":true}
+{"name":"validation-register","width":320,"passed":true}
+{"name":"validation-onboarding","width":320,"passed":true}
+{"name":"projects","width":390,"passed":true}
+{"name":"vacancies","width":390,"passed":true}
+{"name":"programs","width":390,"passed":true}
+{"name":"courses","width":390,"passed":true}
+{"name":"profile","width":390,"passed":true}
+{"name":"profile-edit","width":390,"passed":true}
+{"name":"onboarding-0","width":390,"passed":true}
+{"name":"onboarding-1","width":390,"passed":true}
+{"name":"loading-page","width":390,"passed":true}
+{"name":"loading-action","width":390,"passed":true}
+{"name":"empty","width":390,"passed":true}
+{"name":"error","width":390,"passed":true}
+{"name":"disabled-action","width":390,"passed":true}
+{"name":"disabled-filter","width":390,"passed":true}
+{"name":"validation-register","width":390,"passed":true}
+{"name":"validation-onboarding","width":390,"passed":true}
+{"name":"projects","width":768,"passed":true}
+{"name":"vacancies","width":768,"passed":true}
+{"name":"programs","width":768,"passed":true}
+{"name":"courses","width":768,"passed":true}
+{"name":"profile","width":768,"passed":true}
+{"name":"profile-edit","width":768,"passed":true}
+{"name":"onboarding-0","width":768,"passed":true}
+{"name":"onboarding-1","width":768,"passed":true}
+{"name":"loading-page","width":768,"passed":true}
+{"name":"loading-action","width":768,"passed":true}
+{"name":"empty","width":768,"passed":true}
+{"name":"error","width":768,"passed":true}
+{"name":"disabled-action","width":768,"passed":true}
+{"name":"disabled-filter","width":768,"passed":true}
+{"name":"validation-register","width":768,"passed":true}
+{"name":"validation-onboarding","width":768,"passed":true}
+48 UI state checks passed
+navigation-feed-skills 320: passed
+projects-activity 320: passed
+members 320: passed
+profile-actions 320: passed
+project-actions 320: passed
+program-actions 320: passed
+navigation-feed-skills 390: passed
+projects-activity 390: passed
+members 390: passed
+profile-actions 390: passed
+project-actions 390: passed
+program-actions 390: passed
+navigation-feed-skills 768: passed
+projects-activity 768: passed
+members 768: passed
+profile-actions 768: passed
+project-actions 768: passed
+program-actions 768: passed
+18 interaction screens passed
+6 resize checks passed; routed hosts, search and filters preserved
diff --git a/docs/desktop-regression/unit-tests.log b/docs/desktop-regression/unit-tests.log
new file mode 100644
index 000000000..159f84d5e
--- /dev/null
+++ b/docs/desktop-regression/unit-tests.log
@@ -0,0 +1,1158 @@
+
+> procollab@0.0.0 test:ci
+> vitest run
+
+
+ RUN v3.2.6 Z:/Документы/PROCOLLAB-dev/procollab-dev-platform-responsive
+
+ ✓ projects/social_platform/src/app/ui/widgets/project-invite/profile-project-invite-modal.component.spec.ts (21 tests) 2494ms
+ ✓ Окно выбора проекта > локальный поиск нормализует пробелы и регистр, строка выбирается целиком и выделяется 524ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.spec.ts (7 tests) 2736ms
+ ✓ Окно приглашения из редактора команды > CTA открывает окно с поиском, URL отсутствует, отправка неактивна до выбора и роли 1138ms
+ ✓ Окно приглашения из редактора команды > показывает public data, причины disabled, выбирает строку и очищает выбор 597ms
+ ✓ Окно приглашения из редактора команды > ошибка inline сохраняет выбор/роль, повтор защищён, успех закрывает и возвращает фокус 613ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.spec.ts (30 tests) 3546ms
+ ✓ AnalyticsDrilldownComponent: real overlay lifecycle > all: единое оформление списка и правильный заголовок 1036ms
+ ✓ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.spec.ts (41 tests) 3538ms
+ ✓ InfoCardComponent: статусы моих проектов > 'draft' / 'Лидер': статус, доступ и единственный корректный маршрут 880ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-attention.component.spec.ts (19 tests) 3783ms
+ ✓ Attention views: real overlay > participants: реальные поля, local date, legacy city, fallback, актуальный count 991ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/list/list.component.spec.ts (9 tests) 2742ms
+ ✓ ProjectsListComponent: контекст и track > /my: CTA выполняет один переход в detail 1285ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/feed-news-preview/feed-news-preview.component.spec.ts (23 tests) 5236ms
+ ✓ FeedNewsPreviewComponent > project: нет пустой media-области; thumbnail появляется только с изображением 1471ms
+ ✓ FeedNewsPreviewComponent > Подробнее определяется обрезанием, обновляется при resize и исчезает когда текст помещается 654ms
+ ✓ FeedNewsPreviewComponent > card открывает одно окно 333ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.spec.ts (6 tests) 5475ms
+ ✓ ProfileMainStepComponent user region > loads canonical city as selected user region without API side effects 3037ms
+ ✓ ProfileMainStepComponent user region > preserves untouched legacy city Набережные Челны through focus, blur and Escape 534ms
+ ✓ ProfileMainStepComponent user region > preserves untouched legacy city Мсква through focus, blur and Escape 726ms
+ ✓ ProfileMainStepComponent user region > preserves untouched legacy city moscow through focus, blur and Escape 529ms
+ ✓ ProfileMainStepComponent user region > clears legacy on search, ranks Moscow first and commits only an option to city 368ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.spec.ts (12 tests) 6653ms
+ ✓ ProjectMainStepComponent > стандартная обложка предлагает загрузку и не выдаёт системный URL за загруженный файл 3133ms
+ ✓ ProjectMainStepComponent > пользовательская обложка предлагает только замену с клавиатуры, без кнопки сброса 557ms
+ ✓ ProjectMainStepComponent > замена стандартной и пользовательской обложки загрузкой не вызывает DELETE 762ms
+ ✓ ProjectMainStepComponent > пустая обложка показывает zero state, не записывая фиктивный URL в обязательный control 485ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/edit/edit.component.spec.ts (3 tests) 4495ms
+ ✓ ProfileEditComponent > should create 3495ms
+ ✓ ProfileEditComponent > closes the skills library with the explicit close button 664ms
+ ✓ ProfileEditComponent > closes the skills library through the modal backdrop 313ms
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps unrated CTA active and criteria editable when registration is past but evaluation is future
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ ✓ projects/social_platform/src/app/ui/pages/members/members-mobile.spec.ts (7 tests) 1545ms
+ ✓ Мобильное представление участников > держит статистику перед мобильным списком, под desktop-фильтрами и не перезагружает её при поиске 628ms
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > allows editing an existing rating until the evaluation deadline, then returns to readonly on success
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > allows editing an existing rating until the evaluation deadline, then returns to readonly on success
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-case.component.spec.ts (12 tests) 1507ms
+ ✓ Case drilldown в существующем Overlay > selected: четыре колонки, реальные поля, null presentation и только один modal 671ms
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps expired CTA visible and all criteria readonly (rated=false)
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps expired CTA visible and all criteria readonly (rated=true)
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.spec.ts (3 tests) 1369ms
+ ✓ StageZeroComponent > should create 978ms
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps CTA and criteria available for deadline
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps CTA and criteria available for invalid deadline
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > updates visible CTA and criteria on fresh closed/reopened program responses
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts (8 tests) 1420ms
+ ✓ RatingCardComponent > should create 465ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/main/main.roles.spec.ts (4 tests) 1218ms
+ ✓ Program page: program-scoped news and role visibility > loads and shows both existing and newly created news for manager without member role 964ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/edit.component.spec.ts (3 tests) 1494ms
+ ✓ ProjectEditComponent > should create 1272ms
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (base) > не закрашивает закладку при ошибке подписки
+[15:23:20.269] [ERROR] Error subscribing to project: {"kind":"add_project_subscription_error","cause":{}}
+
+ ✓ projects/social_platform/src/app/ui/pages/projects/projects-presentation.spec.ts (6 tests) 1611ms
+ ✓ ProjectsComponent: приглашение и активность на странице > сохраняет размещение активности в разделе dashboard 986ms
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (base) > сохраняет подписку и подтверждение при ошибке, после успешного повтора закрывает
+[15:23:20.458] [ERROR] Error unsubscribing from project: {"kind":"delete_project_subscription_error","cause":{}}
+
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/news-card.component.spec.ts (5 tests) 979ms
+ ✓ NewsCardComponent > should create 639ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-form/news-form.component.spec.ts (7 tests) 861ms
+ ✓ NewsFormComponent > should create 406ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/detail-cleanup.component.spec.ts (5 tests) 1945ms
+ ✓ Detail cleanup actions > renders create, open-existing and submitted CTA states without changing submitted disabling 1072ms
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (subs) > не закрашивает закладку при ошибке подписки
+[15:23:20.943] [ERROR] Error subscribing to project: {"kind":"add_project_subscription_error","cause":{}}
+
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.spec.ts (8 tests) 1837ms
+ ✓ ProjectAdditionalStepComponent canonical form > required indicators follow backend metadata; optional text has no fake required error 896ms
+ ✓ projects/social_platform/src/app/ui/widgets/info-card/info-card-list-contract.spec.ts (8 tests) 1048ms
+ ✓ Мои проекты: HTTP list → преобразование контракта → карточка > is_submitted=true, draft=false: lifecycle и доступ независимы 601ms
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (subs) > сохраняет подписку и подтверждение при ошибке, после успешного повтора закрывает
+[15:23:21.085] [ERROR] Error unsubscribing from project: {"kind":"delete_project_subscription_error","cause":{}}
+
+ ✓ projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts (8 tests) 1872ms
+ ✓ InfoCard: асинхронная подписка (base) > закрашивает закладку после отложенного ответа без перезагрузки и второго клика 714ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/dashboard/dashboard.component.spec.ts (3 tests) 1237ms
+ ✓ ProjectsDashboard: контексты карточек > передаёт my/subs/base, ID и подписки; показывает нужный контекст каждого раздела 1125ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.spec.ts (42 tests) 13312ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > не показывает общую выгрузку и не запрашивает проекты до открытия кейса 2082ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > клик строки 0 передаёт точный scope, включая нулевой кейс 644ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > клик строки 2 передаёт точный scope, включая нулевой кейс 420ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > клик строки 3 передаёт точный scope, включая нулевой кейс 343ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > keeps cases and evaluation as adjacent cards in the same two-column grid row 321ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > preserves backend counts/order/zero rows and appends withoutCase without mutations 460ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > includes the visible without-case bucket in the common scale 308ms
+ ✓ ProgramAnalyticsComponent > показывает authoritative summary и реальный разрез регионов 305ms
+ ✓ ProgramAnalyticsComponent > non-competitive скрывает строку даже с notSubmitted > 0 и не делает detail request 355ms
+ ✓ ProgramAnalyticsComponent > marks zero attention rows and keeps tooltip controls separate and keyboard accessible 308ms
+ ✓ projects/social_platform/src/app/ui/pages/feed/feed.component.spec.ts (1 test) 894ms
+ ✓ FeedComponent: порядок и представление карточек #372 > сохраняет шесть начальных карточек, ключи type:id и append в DOM без перестановки 892ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-mid-side/profile-mid-side.component.spec.ts (4 tests) 904ms
+ ✓ ProfileMidSideComponent > показывает центрируемый empty state владельцу пустого профиля 611ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.spec.ts (11 tests) 970ms
+ ✓ ProgramRoleWidgetComponent > shows skeleton without bogus zero counters 315ms
+ ✓ projects/social_platform/src/app/ui/primitives/input/input.component.spec.ts (20 tests) 809ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/info.component.spec.ts (3 tests) 911ms
+ ✓ VacancyInfoComponent PROCOLLAB CV > разрешает прикрепить PROCOLLAB CV при пустом accompanyingFile 656ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/register/register.component.spec.ts (4 tests) 1383ms
+ ✓ RegisterComponent > should create 830ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-attention-route.spec.ts (3 tests) 1217ms
+ ✓ Attention SPA: observable route → resolver → overview > participants-without-team отменяется до Program(13), без нового auto request 952ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.spec.ts (2 tests) 787ms
+ ✓ MainComponent > should create 735ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-two/stage-two.component.spec.ts (4 tests) 1260ms
+ ✓ StageTwoComponent > should create 786ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.spec.ts (2 tests) 1539ms
+ ✓ ProgramListComponent > should create 1263ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/login/login.component.spec.ts (4 tests) 753ms
+ ✓ LoginComponent > should create 516ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/main.component.spec.ts (1 test) 959ms
+ ✓ MainComponent > should create 956ms
+stdout | projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts > ProgramRegisterComponent > onSubmit > вызывает use-case с programId и значениями формы
+[15:23:25.982] [DEBUG] Route changed from ProgramRegisterComponent
+
+stdout | projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts > ProgramRegisterComponent > onSubmit > навигирует на детальную страницу программы при успехе use-case
+[15:23:26.066] [DEBUG] Route changed from ProgramRegisterComponent
+
+stdout | projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts > ProgramRegisterComponent > onSubmit > срабатывает по клику на кнопку submit в DOM
+[15:23:26.184] [DEBUG] Route changed from ProgramRegisterComponent
+
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts (7 tests) 963ms
+ ✓ ProgramRegisterComponent > ngOnInit строит форму из schema резолвера > создаёт FormGroup с полем под каждый ключ schema 487ms
+ ✓ projects/social_platform/src/app/ui/widgets/region-select/region-select.component.spec.ts (12 tests) 761ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/register.use-case.spec.ts (5 tests) 70ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/info.component.spec.ts (1 test) 724ms
+ ✓ ProjectInfoComponent > should create 722ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.spec.ts (12 tests) 831ms
+ ✓ VacancyResponsesComponent > показывает два действия только для pending response 495ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/profile-news/profile-news.component.spec.ts (1 test) 567ms
+ ✓ ProfileNewsComponent > should create 565ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/vacancies.component.spec.ts (2 tests) 636ms
+ ✓ VacanciesComponent > should create 513ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-mid-side/projects-mid-side.component.spec.ts (4 tests) 1094ms
+ ✓ ProjectsMidSideComponent > shows the complete project description after expansion 1084ms
+ ✓ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.spec.ts (7 tests) 573ms
+ ✓ Карточка каталога участников > показывает первый навык в исходном порядке и точный +N при 0 навыках 355ms
+ ✓ projects/social_platform/src/app/ui/pages/members/members.component.spec.ts (1 test) 1400ms
+ ✓ MembersComponent > should create 1397ms
+ ✓ projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.spec.ts (10 tests) 962ms
+ ✓ ProjectVacancyCardComponent > should create 545ms
+ ✓ projects/social_platform/src/app/ui/pages/office/office.component.spec.ts (3 tests) 1701ms
+ ✓ OfficeComponent > should create 1509ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-form.service.spec.ts (8 tests) 483ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat-direct/chat-direct.component.spec.ts (1 test) 1246ms
+ ✓ ChatDirectComponent > should create 1234ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/list/list.component.spec.ts (7 tests) 1520ms
+ ✓ VacanciesListComponent > должен вызвать vacancyInfoService.init() при инициализации компонента 1102ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.spec.ts (2 tests) 538ms
+ ✓ ProfileRightSideComponent > keeps the complete long project title in the profile project list DOM 472ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/reset-password/reset-password.component.spec.ts (1 test) 801ms
+ ✓ ResetPasswordComponent > should create 799ms
+ ✓ projects/social_platform/src/app/ui/widgets/chat-window/chat-window.component.spec.ts (1 test) 542ms
+ ✓ ChatWindowComponent > should create 540ms
+ ✓ projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.spec.ts (5 tests) 421ms
+ ✓ VacancyCardComponent > should create 322ms
+stderr | projects/social_platform/src/app/ui/pages/auth/set-password/set-password.component.spec.ts > SetPasswordComponent > should create
+[15:23:34.316] [ERROR] Token is missing
+
+ ✓ projects/social_platform/src/app/ui/pages/auth/set-password/set-password.component.spec.ts (1 test) 455ms
+ ✓ SetPasswordComponent > should create 452ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/invite-card/invite-card.component.spec.ts (4 tests) 867ms
+ ✓ InviteCardComponent > should create 627ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.component.spec.ts (1 test) 1042ms
+ ✓ NewsDetailComponent > should create 1035ms
+ ✓ projects/social_platform/src/app/ui/primitives/tooltip/tooltip.component.spec.ts (4 tests) 708ms
+ ✓ TooltipComponent overlay mode > should use overlay mode for analytics tooltip 537ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.spec.ts (6 tests) 355ms
+stdout | projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.spec.ts > ProjectsFilterComponent > сохраняет справочник отраслей и фильтрацию через query-параметр industry
+[15:23:35.977] [DEBUG] Query change from ProjectsComponent
+
+ ✓ projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.spec.ts (2 tests) 648ms
+ ✓ ProjectsFilterComponent > should create 575ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/program-projects-filter/program-projects-filter.component.spec.ts (2 tests) 765ms
+ ✓ ProjectsFilterComponent > should create 594ms
+ ✓ projects/social_platform/src/app/ui/primitives/select/select.component.spec.ts (7 tests) 773ms
+ ✓ SelectComponent > should create 530ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.spec.ts (6 tests) 484ms
+ ✓ ProfileLeftSideComponent > renders programs as compact named rectangular links 341ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/detail/info/course-module-card/course-module-card.component.spec.ts (7 tests) 561ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-one/stage-one.component.spec.ts (1 test) 487ms
+ ✓ StageOneComponent > should create 483ms
+ ✓ projects/social_platform/src/app/ui/primitives/avatar-control/avatar-control.component.spec.ts (1 test) 408ms
+ ✓ AvatarControlComponent > should create 406ms
+ ✓ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.spec.ts (6 tests) 553ms
+ ✓ TextareaComponent > should create 323ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/feed-news-modal/feed-news-modal.component.spec.ts (1 test) 631ms
+ ✓ FeedNewsModalComponent > показывает полный текст, переносы, ссылку, все файлы и contain-карусель без detail HTTP 628ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-partner.use-case.spec.ts (3 tests) 66ms
+ ✓ projects/social_platform/src/app/ui/pages/program/main/main.component.spec.ts (1 test) 673ms
+ ✓ MainComponent > should create 668ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/project-activity-card/project-activity-card.component.spec.ts (11 tests) 690ms
+ ✓ ProjectActivityCardComponent > показывает четыре значения authoritative count 396ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat.component.spec.ts (1 test) 558ms
+ ✓ ChatComponent > should create 552ms
+ ✓ projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.spec.ts (15 tests) 523ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-left-side/projects-left-side.component.spec.ts (4 tests) 583ms
+ ✓ ProjectsLeftSideComponent > should show explicit project metadata labels 397ms
+ ✓ projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.spec.ts (1 test) 639ms
+ ✓ OpenVacancyComponent > показывает тип, дату, источник, роль, описание, навыки и CTA 637ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/get-profile-news-detail.use-case.spec.ts (3 tests) 100ms
+ ✓ projects/social_platform/src/app/ui/primitives/modal/modal.component.spec.ts (4 tests) 417ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.spec.ts (2 tests) 537ms
+ ✓ VacanciesDetailComponent > should create 411ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.spec.ts (9 tests) 414ms
+ ✓ projects/social_platform/src/app/ui/pages/office/delete-confirm/delete-confirm.component.spec.ts (1 test) 334ms
+ ✓ DeleteConfirmComponent > should create 332ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-goals-http.adapter.spec.ts (4 tests) 78ms
+ ✓ projects/social_platform/src/app/ui/pages/members/member-statistics-card/member-statistics-card.component.spec.ts (11 tests) 471ms
+ ✓ projects/social_platform/src/app/utils/export-regions-workbook.spec.ts (1 test) 387ms
+ ✓ region XLSX workbook integration > generates a ZIP/OOXML workbook with real string and number cells 382ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/chat/chat.component.spec.ts (1 test) 484ms
+ ✓ ChatComponent > should create 481ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/video-task/info-task.component.spec.ts (1 test) 284ms
+ ✓ projects/social_platform/src/app/ui/widgets/chat-window/chat-message/chat-message.component.spec.ts (1 test) 454ms
+ ✓ ChatMessageComponent > should create 451ms
+ ✓ projects/social_platform/src/app/ui/widgets/specializations-group/specializations-group.component.spec.ts (4 tests) 347ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.spec.ts (1 test) 383ms
+ ✓ CourseComponent > should create 378ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-cover-reset.service.spec.ts (11 tests) 300ms
+ ✓ projects/social_platform/src/app/api/searches/searches.service.spec.ts (5 tests) 75ms
+ ✓ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.spec.ts (3 tests) 425ms
+ ✓ AutoCompleteInputComponent: последовательные запросы > повторяет тот же поиск после выбора и программной очистки 348ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.spec.ts (1 test) 306ms
+ ✓ WriteTaskComponent > should create 303ms
+ ✓ projects/social_platform/src/app/app.component.spec.ts (1 test) 271ms
+ ✓ projects/social_platform/src/app/ui/primitives/avatar/avatar.component.spec.ts (6 tests) 269ms
+ ✓ projects/ui/src/lib/components/layout/invite-manage-card/invite-manage-card.component.spec.ts (1 test) 311ms
+ ✓ InviteManageCardComponent > should create 309ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/projects-edit-info.service.spec.ts (22 tests) 373ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/complete/complete.component.spec.ts (5 tests) 295ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/revoke-invite.use-case.spec.ts (3 tests) 86ms
+ ✓ projects/social_platform/src/app/ui/widgets/cookie-consent/cookie-consent.component.spec.ts (5 tests) 283ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/collaborator-card/collaborator-card.component.spec.ts (2 tests) 379ms
+ ✓ CollaboratorCardComponent > should create 313ms
+stdout | projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.spec.ts > FeedComponent > показывает счётчики всех шести категорий независимо от фильтра
+[15:23:46.215] [DEBUG] Query change from FeedFilterComponent
+
+ ✓ projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.spec.ts (2 tests) 411ms
+ ✓ projects/social_platform/src/app/ui/widgets/header/header.component.spec.ts (1 test) 362ms
+ ✓ HeaderComponent > should create 359ms
+ ✓ projects/social_platform/src/app/ui/pages/members/members-filters/members-filters.component.spec.ts (2 tests) 409ms
+ ✓ MembersFiltersComponent > should create 359ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-vacancy-responses.use-case.spec.ts (2 tests) 66ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/remove-project-collaborator.use-case.spec.ts (3 tests) 63ms
+ ✓ projects/social_platform/src/app/ui/widgets/message-input/message-input.component.spec.ts (1 test) 287ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-left-side/vacancies-left-side.component.spec.ts (1 test) 312ms
+ ✓ VacanciesLeftSideComponent > renders vacancy detail skills with the readable tag treatment 310ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-three/stage-three.component.spec.ts (1 test) 380ms
+ ✓ StageThreeComponent > should create 378ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.spec.ts (5 tests) 251ms
+ ✓ projects/social_platform/src/app/ui/primitives/bar/bar.component.spec.ts (1 test) 245ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.spec.ts (1 test) 290ms
+ ✓ projects/social_platform/src/app/ui/pages/feed/new-project/new-project.component.spec.ts (1 test) 262ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-additional.service.spec.ts (39 tests) 286ms
+ ✓ projects/social_platform/src/app/ui/widgets/skills-group/skills-group.component.spec.ts (4 tests) 408ms
+ ✓ SkillsGroupComponent > should create 300ms
+ ✓ projects/social_platform/src/app/ui/widgets/project-invite/project-invite-role-input.component.spec.ts (4 tests) 299ms
+ ✓ projects/social_platform/src/app/ui/widgets/vacancy-filter/vacancy-filter.component.spec.ts (1 test) 342ms
+ ✓ FeedComponent > should create 340ms
+ ✓ projects/social_platform/src/app/domain/shared/chat-state.service.spec.ts (1 test) 34ms
+ ✓ projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.spec.ts (1 test) 246ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/carousel/carousel.component.spec.ts (2 tests) 240ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-form.service.spec.ts (13 tests) 271ms
+ ✓ projects/social_platform/src/app/api/feed/facades/feed-info.service.spec.ts (3 tests) 148ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-analytics-attention.service.spec.ts (42 tests) 359ms
+ ✓ projects/social_platform/src/app/ui/widgets/skills-basket/skills-basket.component.spec.ts (4 tests) 569ms
+ ✓ SkillsBasketComponent > should create 383ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-vacancies.use-case.spec.ts (3 tests) 102ms
+ ✓ projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.spec.ts (2 tests) 547ms
+ ✓ VacancySkillsComponent > показывает правильное число остальных навыков, раскрывает весь список и сворачивает его 516ms
+ ✓ projects/social_platform/src/app/ui/primitives/file-upload-item/file-upload-item.component.spec.ts (1 test) 321ms
+ ✓ FileUploadItemComponent > should create 319ms
+ ✓ projects/core/src/lib/interceptors/camelcase.interceptor.spec.ts (6 tests) 127ms
+ ✓ projects/social_platform/src/app/ui/primitives/switch/switch.component.spec.ts (4 tests) 226ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.spec.ts (1 test) 332ms
+ ✓ BarNewComponent > should create 330ms
+ ✓ projects/ui/src/lib/components/primitives/avatar/avatar.component.spec.ts (6 tests) 421ms
+ ✓ AvatarComponent > should create 320ms
+ ✓ projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.spec.ts (1 test) 225ms
+ ✓ projects/ui/src/lib/components/primitives/back/back.component.spec.ts (1 test) 263ms
+ ✓ projects/social_platform/src/app/api/member/facades/members-info.service.spec.ts (16 tests) 277ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.spec.ts (1 test) 249ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/program/program.repository.spec.ts (30 tests) 272ms
+ ✓ projects/ui/src/lib/components/primitives/icon/icon.component.spec.ts (5 tests) 259ms
+ ✓ projects/social_platform/src/app/ui/primitives/search/search.component.spec.ts (2 tests) 230ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/onboarding.component.spec.ts (1 test) 208ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-form-autosave.service.spec.ts (24 tests) 221ms
+ ✓ projects/social_platform/src/app/ui/pages/error/error-code/error-code.component.spec.ts (1 test) 197ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.spec.ts (1 test) 278ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-analytics-info.service.spec.ts (15 tests) 146ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-vacancy.service.spec.ts (13 tests) 217ms
+ ✓ projects/social_platform/src/app/ui/primitives/loader/loader.component.spec.ts (4 tests) 179ms
+ ✓ projects/social_platform/src/app/ui/primitives/button/button.component.spec.ts (6 tests) 373ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/detail/info/course-module-card/circle-progress-bar/circle-progress-bar.component.spec.ts (1 test) 389ms
+ ✓ CircleProgressBarComponent > should create 383ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-collaborators-http.adapter.spec.ts (3 tests) 63ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-goals.repository.spec.ts (4 tests) 86ms
+ ✓ projects/social_platform/src/app/ui/primitives/img-card/img-card.component.spec.ts (1 test) 203ms
+ ✓ projects/core/src/lib/services/error/error.service.spec.ts (1 test) 53ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-manager-overview.use-case.spec.ts (2 tests) 84ms
+ ✓ projects/ui/src/lib/components/layout/sidebar/sidebar.component.spec.ts (1 test) 298ms
+ ✓ projects/social_platform/src/app/ui/primitives/icon/icon.component.spec.ts (5 tests) 352ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-role-widget.service.spec.ts (11 tests) 194ms
+ ✓ projects/ui/src/lib/components/primitives/button/button-states.spec.ts (2 tests) 281ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-all-members.use-case.spec.ts (3 tests) 58ms
+ ✓ projects/social_platform/src/app/api/vacancy/facades/vacancy-detail-info.service.spec.ts (17 tests) 225ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/auth/auth.repository.spec.ts (17 tests) 209ms
+ ✓ projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.spec.ts (5 tests) 298ms
+ ✓ projects/ui/src/lib/components/layout/profile-info/profile-info.component.spec.ts (1 test) 241ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/ui/project-team-ui.service.spec.ts (2 tests) 78ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/confirm-password-reset/confirm-password-reset.component.spec.ts (1 test) 266ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/program/program-http.adapter.spec.ts (22 tests) 188ms
+ ✓ projects/social_platform/src/app/ui/primitives/tag/tag.component.spec.ts (1 test) 228ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-three/user-type-card/user-type-card.component.spec.ts (1 test) 193ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-edit-message.use-case.spec.ts (2 tests) 65ms
+ ✓ projects/social_platform/src/app/api/kanban/use-cases/get-board.use-case.spec.ts (4 tests) 84ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/confirm-email/confirm-email.component.spec.ts (1 test) 478ms
+ ✓ ConfirmEmailComponent > should create 473ms
+ ✓ projects/social_platform/src/app/ui/pages/error/error.component.spec.ts (1 test) 164ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/auth/auth-http.adapter.spec.ts (24 tests) 284ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/services/profile/detail-profile-invite.spec.ts (9 tests) 143ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/ui/project-vacancy-ui.service.spec.ts (17 tests) 232ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-manager-attention.use-case.spec.ts (23 tests) 231ms
+ ✓ projects/core/src/lib/services/websockets/websocket.service.spec.ts (1 test) 42ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project.repository.spec.ts (21 tests) 322ms
+ ✓ projects/social_platform/src/app/ui/primitives/file-item/file-item.component.spec.ts (1 test) 292ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/send-vacancy-response.use-case.spec.ts (4 tests) 106ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project.use-case.spec.ts (3 tests) 63ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-team.service.spec.ts (19 tests) 243ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-typing.use-case.spec.ts (2 tests) 42ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-vacancy-detail.use-case.spec.ts (3 tests) 64ms
+ ✓ projects/social_platform/src/app/ui/pages/error/not-found/error-not-found.component.spec.ts (1 test) 123ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-set-online.use-case.spec.ts (2 tests) 83ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/services/program/detail-program-info.service.spec.ts (15 tests) 163ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-role-widget.use-case.spec.ts (7 tests) 139ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/delete-profile-news.use-case.spec.ts (3 tests) 67ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/detail.resolver.spec.ts (10 tests) 104ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/fetch-profile-news.use-case.spec.ts (3 tests) 51ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-resources.use-case.spec.ts (3 tests) 64ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat-direct/chat-direct.resolver.spec.ts (1 test) 50ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/add-project-subscription.use-case.spec.ts (3 tests) 84ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/reject-invite.use-case.spec.ts (3 tests) 123ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/invite/invite.repository.spec.ts (9 tests) 218ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-all-projects.use-case.spec.ts (3 tests) 59ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/services/rating-card.service.spec.ts (9 tests) 122ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-edit-info.service.spec.ts (4 tests) 258ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/vacancy/vacancy.repository.spec.ts (16 tests) 257ms
+ ✓ projects/social_platform/src/app/api/onboarding/facades/stages/onboarding-stage-zero-info.service.spec.ts (7 tests) 189ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/skills/skills.repository.spec.ts (2 tests) 86ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/auth.component.spec.ts (1 test) 144ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-form.factory.spec.ts (4 tests) 31ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/reset-project-cover.use-case.spec.ts (13 tests) 130ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/save-profile.use-case.spec.ts (3 tests) 207ms
+ ✓ projects/social_platform/src/app/ui/pages/office/snackbar/animation/animation.service.spec.ts (1 test) 45ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/program-case-projects.use-case.spec.ts (15 tests) 147ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/program-link-fields.use-cases.spec.ts (15 tests) 552ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/accept-invite.use-case.spec.ts (3 tests) 422ms
+ ✓ AcceptInviteUseCase > делегирует inviteId в репозиторий и эмитит событие 341ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-programs.use-case.spec.ts (3 tests) 138ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-project.use-case.spec.ts (3 tests) 117ms
+ ✓ projects/social_platform/src/app/api/invite/mappers/map-invite-send-error.spec.ts (24 tests) 102ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-case-projects.service.spec.ts (11 tests) 134ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-analytics-drilldown.service.spec.ts (10 tests) 154ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-project.use-case.spec.ts (3 tests) 85ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/chat/chat-ws.adapter.spec.ts (14 tests) 172ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/profile/profile-news-http.adapter.spec.ts (7 tests) 80ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/update-profile.use-case.spec.ts (3 tests) 69ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/member/member-statistics-contract.spec.ts (6 tests) 102ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/reject-response.use-case.spec.ts (3 tests) 77ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/delete-news.use-case.spec.ts (3 tests) 90ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/submit-competitive-project.use-case.spec.ts (3 tests) 79ms
+ ✓ projects/social_platform/src/app/api/feed/use-cases/read-feed-news.use-case.spec.ts (4 tests) 162ms
+ ✓ projects/core/src/lib/services/error/global-error-handler.service.spec.ts (1 test) 220ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/chat/chat-http.adapter.spec.ts (4 tests) 86ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-collaborators.repository.spec.ts (3 tests) 70ms
+ ✓ projects/social_platform/src/app/api/auth/auth.service.spec.ts (1 test) 65ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-rating-http.adapter.spec.ts (4 tests) 154ms
+ ✓ projects/social_platform/src/app/api/member/facades/member-statistics.facade.spec.ts (5 tests) 569ms
+ ✓ Состояние глобальной статистики участников > остаётся loading до ответа и выполняет только один запрос за жизнь страницы 439ms
+ ✓ projects/social_platform/src/app/api/project/facades/projects-info.service.spec.ts (3 tests) 421ms
+ ✓ ProjectsInfoService: загрузка активности > запрашивает count при входе на /office/projects/dashboard 347ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-rating.repository.spec.ts (6 tests) 107ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-program-http.adapter.spec.ts (3 tests) 65ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-contacts.service.spec.ts (3 tests) 111ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/program/program-case-http.integration.spec.ts (2 tests) 99ms
+ ✓ projects/core/src/lib/interceptors/bearer-token.interceptor.spec.ts (1 test) 49ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/list/my.resolver.spec.ts (1 test) 68ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/update-form.use-case.spec.ts (3 tests) 302ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-news.repository.spec.ts (8 tests) 347ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/update-vacancy.use-case.spec.ts (3 tests) 73ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/program/program-news.repository.spec.ts (6 tests) 110ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-subscriptions.use-case.spec.ts (3 tests) 75ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-project-responses.use-case.spec.ts (3 tests) 209ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat-groups.resolver.spec.ts (1 test) 32ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-goals.use-case.spec.ts (3 tests) 70ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-course-lesson.use-case.spec.ts (3 tests) 68ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/toggle-profile-news-like.use-case.spec.ts (3 tests) 194ms
+ ✓ projects/social_platform/src/app/api/feed/use-cases/toggle-feed-like.use-case.spec.ts (4 tests) 147ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/update-invite.use-case.spec.ts (3 tests) 60ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/get-my-invites.use-case.spec.ts (3 tests) 149ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/profile/profile-news.repository.spec.ts (8 tests) 209ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/assign-project-program.spec.ts (3 tests) 96ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-program.repository.spec.ts (5 tests) 75ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/specializations/specializations.repository.spec.ts (2 tests) 47ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/read-profile-news.use-case.spec.ts (3 tests) 98ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-resource.use-case.spec.ts (3 tests) 149ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/member/member.repository.spec.ts (1 test) 94ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-project-subscription.use-case.spec.ts (3 tests) 79ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-my-projects.use-case.spec.ts (3 tests) 180ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-set-offline.use-case.spec.ts (2 tests) 45ms
+ ✓ projects/social_platform/src/app/api/program/program-widget-refresh.spec.ts (8 tests) 112ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/chat/chat-realtime.repository.spec.ts (3 tests) 127ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.resolver.spec.ts (1 test) 77ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/register-program.use-case.spec.ts (3 tests) 63ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-messages.use-case.spec.ts (2 tests) 92ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/industry/industry.repository.spec.ts (3 tests) 106ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-subscribers.use-case.spec.ts (3 tests) 95ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-filters.use-case.spec.ts (3 tests) 61ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-news-http.adapter.spec.ts (7 tests) 209ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/create-program-filters.use-case.spec.ts (3 tests) 113ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/read-project-news.use-case.spec.ts (3 tests) 96ms
+ ✓ projects/social_platform/src/app/api/invite/facades/invite-participant-search.facade.spec.ts (4 tests) 104ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/send-for-user.use-case.spec.ts (3 tests) 81ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/participating-program.use-case.spec.ts (3 tests) 94ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/program/program-news-http.adapter.spec.ts (6 tests) 149ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/info.resolver.spec.ts (1 test) 54ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/ui/program-detail-main-ui-info.service.spec.ts (13 tests) 76ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/courses/courses.repository.spec.ts (5 tests) 94ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/member/member-http.adapter.spec.ts (2 tests) 88ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/projects-activity-placement.spec.ts (4 tests) 9ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-http.adapter.spec.ts (8 tests) 218ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/fetch-project-news.use-case.spec.ts (3 tests) 72ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/login.use-case.spec.ts (4 tests) 137ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-goals.use-case.spec.ts (3 tests) 67ms
+ ✓ projects/social_platform/src/app/api/skills/use-cases/search-skills.use-case.spec.ts (3 tests) 111ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/transfer-project-ownership.use-case.spec.ts (3 tests) 82ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/post-vacancy.use-case.spec.ts (3 tests) 104ms
+ ✓ projects/social_platform/src/app/api/vacancy/facades/vacancy-info.service.spec.ts (4 tests) 130ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/start-typing.use-case.spec.ts (1 test) 114ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-manager-assignments.use-case.spec.ts (6 tests) 295ms
+ ✓ projects/social_platform/src/app/api/feed/use-cases/fetch-feed.use-case.spec.ts (3 tests) 271ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-subscription.repository.spec.ts (4 tests) 87ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/rate-project.use-case.spec.ts (3 tests) 113ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/edit.resolver.spec.ts (1 test) 202ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/vacancy/vacancy-http.adapter.spec.ts (5 tests) 277ms
+ ✓ projects/social_platform/src/app/domain/shared/entity-cache.spec.ts (11 tests) 45ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-detail-main-info.service.spec.ts (3 tests) 141ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-partner.repository.spec.ts (4 tests) 447ms
+ ✓ projects/core/src/consts/lists/russian-regions-list.const.spec.ts (7 tests) 80ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/filter-project-ratings.use-case.spec.ts (3 tests) 75ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/services/detail-info.service.spec.ts (1 test) 83ms
+ ✓ projects/social_platform/src/app/api/onboarding/facades/stages/ui/onboarding-stage-one-ui-info.service.spec.ts (1 test) 53ms
+ ✓ projects/social_platform/src/app/api/courses/facades/ui/course-detail-ui-info.service.spec.ts (5 tests) 86ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/load-project-files.use-case.spec.ts (3 tests) 56ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/connect-chat.use-case.spec.ts (1 test) 98ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-courses.use-case.spec.ts (3 tests) 66ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/feed/feed-http.adapter.spec.ts (1 test) 41ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/skills/skills-http.adapter.spec.ts (2 tests) 63ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/invite/invite-http.adapter.spec.ts (7 tests) 292ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/subscription/subscription-http.adapter.spec.ts (4 tests) 92ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/courses/courses-http.adapter.spec.ts (5 tests) 99ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/check-unreads.use-case.spec.ts (3 tests) 200ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-partners.use-case.spec.ts (3 tests) 80ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-project-ratings.use-case.spec.ts (3 tests) 250ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/reset-password.use-case.spec.ts (3 tests) 158ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-count-contract.spec.ts (1 test) 67ms
+ ✓ projects/core/src/lib/services/validation/validation.service.spec.ts (1 test) 50ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/load-messages.use-case.spec.ts (3 tests) 83ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/toggle-like.use-case.spec.ts (3 tests) 193ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat.resolver.spec.ts (1 test) 50ms
+ ✓ projects/social_platform/src/app/ui/primitives/modal/modal.service.spec.ts (1 test) 123ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-cover-contract.spec.ts (3 tests) 241ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/add-profile-news.use-case.spec.ts (3 tests) 238ms
+ ✓ projects/social_platform/src/app/api/kanban/use-cases/get-task.use-case.spec.ts (4 tests) 92ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-course-structure.use-case.spec.ts (3 tests) 87ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-partner.use-case.spec.ts (3 tests) 146ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/download-cv.use-case.spec.ts (3 tests) 71ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-resource-http.adapter.spec.ts (4 tests) 133ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-resource.repository.spec.ts (4 tests) 83ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-project-news.use-case.spec.ts (3 tests) 228ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/read-news.use-case.spec.ts (3 tests) 94ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/update-resource.use-case.spec.ts (3 tests) 265ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-news-detail.use-case.spec.ts (3 tests) 97ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-course-detail.use-case.spec.ts (3 tests) 199ms
+ ✓ projects/core/src/lib/guards/auth/auth-required.guard.spec.ts (1 test) 89ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/get-project-invites.use-case.spec.ts (3 tests) 109ms
+ ✓ projects/core/src/lib/services/tokens/token.service.spec.ts (1 test) 57ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/chat/chat.repository.spec.ts (3 tests) 104ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/submit-task-answer.use-case.spec.ts (3 tests) 95ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/edit-project-news.use-case.spec.ts (3 tests) 223ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/chat/chat.resolver.spec.ts (1 test) 130ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/program-projects-filter/service/program-projects-filter-info.service.spec.ts (1 test) 62ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/send-message.use-case.spec.ts (1 test) 305ms
+ ✓ projects/social_platform/src/app/api/program/program-widget-presentation.spec.ts (30 tests) 84ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/feed/feed.repository.spec.ts (1 test) 71ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-my-vacancies.use-case.spec.ts (3 tests) 213ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/resend-email.use-case.spec.ts (3 tests) 88ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-goal.use-case.spec.ts (3 tests) 269ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-partner-http.adapter.spec.ts (4 tests) 117ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/projects.resolver.spec.ts (2 tests) 419ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/toggle-project-news-like.use-case.spec.ts (3 tests) 353ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-resource.use-case.spec.ts (3 tests) 72ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-data-schema.use-case.spec.ts (3 tests) 64ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/edit-news.use-case.spec.ts (3 tests) 74ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program.use-case.spec.ts (3 tests) 115ms
+ ✓ projects/social_platform/src/app/api/kanban/use-cases/get-column-tasks.use-case.spec.ts (3 tests) 392ms
+ ✓ projects/social_platform/src/app/api/member/use-cases/get-members.use-case.spec.ts (4 tests) 469ms
+ ✓ GetMembersUseCase > делегирует вызов с skip/take/params 437ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/fetch-news.use-case.spec.ts (3 tests) 209ms
+ ✓ projects/social_platform/src/app/ui/services/notification/notification.service.spec.ts (1 test) 89ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/update-goal.use-case.spec.ts (3 tests) 119ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/accept-response.use-case.spec.ts (3 tests) 362ms
+ ✓ projects/social_platform/src/app/api/member/member-filters.spec.ts (10 tests) 145ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/list/all.resolver.spec.ts (1 test) 51ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/apply-project-to-program.use-case.spec.ts (3 tests) 326ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/set-password.use-case.spec.ts (3 tests) 248ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/edit-message.use-case.spec.ts (1 test) 215ms
+ ✓ projects/social_platform/src/app/api/skills/use-cases/get-skills-nested.use-case.spec.ts (3 tests) 158ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-read-message.use-case.spec.ts (2 tests) 107ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/add-news.use-case.spec.ts (3 tests) 82ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/add-project-news.use-case.spec.ts (3 tests) 116ms
+ ✓ projects/social_platform/src/app/api/onboarding/onboarding.service.spec.ts (1 test) 42ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/edit-profile-news.use-case.spec.ts (3 tests) 228ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/specializations/specializations-http.adapter.spec.ts (2 tests) 62ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/leave-project.use-case.spec.ts (3 tests) 296ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/register/register.resolver.spec.ts (1 test) 39ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/delete-message.use-case.spec.ts (1 test) 288ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-all-projects.use-case.spec.ts (3 tests) 343ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/industry/industry-http.adapter.spec.ts (1 test) 140ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-delete-message.use-case.spec.ts (2 tests) 206ms
+ ✓ projects/core/src/lib/services/file/file.service.spec.ts (1 test) 182ms
+ ✓ projects/core/src/lib/services/api/api.service.spec.ts (1 test) 45ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-save-error.utils.spec.ts (5 tests) 17ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/read-message.use-case.spec.ts (1 test) 42ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/delete-vacancy.use-case.spec.ts (3 tests) 229ms
+ ✓ projects/social_platform/src/app/domain/invite/invite-candidates.spec.ts (2 tests) 23ms
+ ✓ projects/social_platform/src/app/api/profile/facades/detail/ui/profile-detail-ui-info.service.spec.ts (4 tests) 20ms
+ ✓ projects/social_platform/src/app/api/feed/facades/ui/feed-ui-info.service.spec.ts (1 test) 16ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-edit-validation.utils.spec.ts (9 tests) 111ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/courses/local-storage-seen-modules.adapter.spec.ts (4 tests) 18ms
+ ✓ projects/core/src/lib/pipes/formatters/parse-breaks.pipe.spec.ts (1 test) 10ms
+ ✓ projects/core/src/lib/pipes/formatters/years-from-birthday.pipe.spec.ts (1 test) 6ms
+ ✓ projects/social_platform/src/app/utils/program-case-analytics.spec.ts (14 tests) 54ms
+ ✓ projects/core/src/lib/pipes/formatters/parse-links.pipe.spec.ts (1 test) 14ms
+ ✓ projects/social_platform/src/app/api/vacancy/vacancy-response-error.spec.ts (8 tests) 16ms
+ ✓ projects/core/src/lib/pipes/user/user-role.pipe.spec.ts (1 test) 10ms
+ ✓ projects/core/src/lib/pipes/controls/control-error.pipe.spec.ts (1 test) 6ms
+ ✓ projects/core/src/lib/pipes/transformers/link-transform.pipe.spec.ts (1 test) 14ms
+ ✓ projects/social_platform/src/app/api/project/facades/detail/ui/projects-detail-ui.service.spec.ts (1 test) 8ms
+ ✓ projects/core/src/lib/pipes/formatters/pluralize.pipe.spec.ts (1 test) 6ms
+ ✓ projects/social_platform/src/app/utils/program-analytics-assignment.spec.ts (9 tests) 26ms
+ ✓ projects/core/src/lib/pipes/transformers/salary-trasform.pipe.spec.ts (1 test) 10ms
+ ✓ projects/core/src/lib/pipes/controls/form-control.pipe.spec.ts (1 test) 10ms
+ ✓ projects/core/src/lib/pipes/formatters/dayjs.pipe.spec.ts (1 test) 14ms
+ ✓ projects/core/src/lib/pipes/user/user-links.pipe.spec.ts (1 test) 8ms
+ ✓ projects/social_platform/src/app/ui/pipes/file-type.pipe.spec.ts (1 test) 7ms
+ ✓ projects/social_platform/src/app/ui/routes/program/detail.routes.spec.ts (2 tests) 6ms
+ ✓ projects/social_platform/src/app/utils/export-regions.spec.ts (3 tests) 13ms
+
+ Test Files 406 passed (406)
+ Tests 2006 passed (2006)
+ Start at 15:22:42
+ Duration 136.04s (transform 45.00s, setup 747.86s, collect 367.88s, tests 170.23s, environment 49.86s, prepare 154.39s)
diff --git a/docs/desktop-regression/visual.log b/docs/desktop-regression/visual.log
new file mode 100644
index 000000000..5a4118ef6
--- /dev/null
+++ b/docs/desktop-regression/visual.log
@@ -0,0 +1,230 @@
+desktop-after: feed 1440
+desktop-after: projects 1440
+desktop-after: my-projects 1440
+desktop-after: members 1440
+desktop-after: programs 1440
+desktop-after: program 1440
+desktop-after: profile 1440
+desktop-after: project 1440
+desktop-after: vacancies 1440
+desktop-after: vacancy 1440
+desktop-after: courses 1440
+desktop-after: course 1440
+desktop-after: feed 1920
+desktop-after: projects 1920
+desktop-after: my-projects 1920
+desktop-after: members 1920
+desktop-after: programs 1920
+desktop-after: program 1920
+desktop-after: profile 1920
+desktop-after: project 1920
+desktop-after: vacancies 1920
+desktop-after: vacancy 1920
+desktop-after: courses 1920
+desktop-after: course 1920
+desktop-after: empty-feed 1440
+desktop-after: empty-vacancies 1440
+desktop-after: empty-courses 1440
+desktop-after: empty-feed 1920
+desktop-after: empty-vacancies 1920
+desktop-after: empty-courses 1920
+desktop-after: profile-edit 1440
+desktop-after: project-edit 1440
+desktop-after: profile-edit 1920
+desktop-after: project-edit 1920
+desktop-after: loading-action 1440
+desktop-after: loading-action 1920
+mobile-after: feed 320
+mobile-after: projects 320
+mobile-after: my-projects 320
+mobile-after: members 320
+mobile-after: programs 320
+mobile-after: program 320
+mobile-after: profile 320
+mobile-after: project 320
+mobile-after: vacancies 320
+mobile-after: vacancy 320
+mobile-after: courses 320
+mobile-after: course 320
+mobile-after: feed 390
+mobile-after: projects 390
+mobile-after: my-projects 390
+mobile-after: members 390
+mobile-after: programs 390
+mobile-after: program 390
+mobile-after: profile 390
+mobile-after: project 390
+mobile-after: vacancies 390
+mobile-after: vacancy 390
+mobile-after: courses 390
+mobile-after: course 390
+mobile-after: feed 768
+mobile-after: projects 768
+mobile-after: my-projects 768
+mobile-after: members 768
+mobile-after: programs 768
+mobile-after: program 768
+mobile-after: profile 768
+mobile-after: project 768
+mobile-after: vacancies 768
+mobile-after: vacancy 768
+mobile-after: courses 768
+mobile-after: course 768
+mobile-after: profile-edit 320
+mobile-after: project-edit 320
+mobile-after: profile-edit 390
+mobile-after: project-edit 390
+mobile-after: profile-edit 768
+mobile-after: project-edit 768
+PASS course-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS course-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS courses-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS courses-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-courses-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-courses-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-feed-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-feed-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-vacancies-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-vacancies-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS feed-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS feed-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+FAIL loading-action-1440: exact=1027px; delta>8=0.0812% (1440, 844) -> (1440, 844) bbox=[905, 733, 1237, 758]
+FAIL loading-action-1920: exact=1027px; delta>8=0.0609% (1920, 844) -> (1920, 844) bbox=[1443, 733, 1775, 758]
+PASS members-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS members-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS my-projects-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS my-projects-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS profile-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS profile-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS profile-edit-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS profile-edit-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS program-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS program-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS programs-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS programs-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS project-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS project-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS project-edit-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS project-edit-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS projects-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS projects-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS vacancies-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS vacancies-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS vacancy-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS vacancy-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+desktop-after: loading-action 1440
+desktop-after: loading-action 1920
+PASS course-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS course-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS courses-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS courses-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-courses-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-courses-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-feed-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-feed-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-vacancies-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-vacancies-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS feed-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS feed-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS loading-action-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS loading-action-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS members-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS members-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS my-projects-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS my-projects-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS profile-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS profile-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS profile-edit-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS profile-edit-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS program-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS program-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS programs-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS programs-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS project-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS project-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS project-edit-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS project-edit-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS projects-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS projects-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS vacancies-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS vacancies-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS vacancy-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS vacancy-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS course-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS course-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS courses-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS courses-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-courses-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-courses-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-feed-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-feed-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS empty-vacancies-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS empty-vacancies-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS feed-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS feed-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS loading-action-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS loading-action-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS members-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS members-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS my-projects-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS my-projects-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS profile-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS profile-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS profile-edit-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS profile-edit-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS program-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS program-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS programs-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS programs-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS project-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS project-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS project-edit-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS project-edit-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS projects-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS projects-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS vacancies-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS vacancies-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS vacancy-1440: exact=0px; delta>8=0.0000% (1440, 844) -> (1440, 844) bbox=None
+PASS vacancy-1920: exact=0px; delta>8=0.0000% (1920, 844) -> (1920, 844) bbox=None
+PASS course-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS course-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS course-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS courses-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS courses-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS courses-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS feed-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS feed-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS feed-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS members-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS members-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS members-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS my-projects-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS my-projects-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS my-projects-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS profile-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS profile-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS profile-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS profile-edit-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS profile-edit-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS profile-edit-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS program-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS program-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS program-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS programs-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS programs-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS programs-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS project-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS project-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS project-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS project-edit-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS project-edit-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS project-edit-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS projects-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS projects-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS projects-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS vacancies-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS vacancies-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS vacancies-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
+PASS vacancy-320: exact=0px; delta>8=0.0000% (320, 844) -> (320, 844) bbox=None
+PASS vacancy-390: exact=0px; delta>8=0.0000% (390, 844) -> (390, 844) bbox=None
+PASS vacancy-768: exact=0px; delta>8=0.0000% (768, 844) -> (768, 844) bbox=None
diff --git a/docs/mobile-polish/.gitattributes b/docs/mobile-polish/.gitattributes
new file mode 100644
index 000000000..8ea60f1b9
--- /dev/null
+++ b/docs/mobile-polish/.gitattributes
@@ -0,0 +1,3 @@
+*.json linguist-generated=true
+*.log linguist-generated=true
+screenshots/** linguist-generated=true
diff --git a/docs/mobile-polish/README.md b/docs/mobile-polish/README.md
new file mode 100644
index 000000000..0d74bdddc
--- /dev/null
+++ b/docs/mobile-polish/README.md
@@ -0,0 +1,79 @@
+
+
+# Исправления мобильной компоновки после PR #401
+
+Desktop-эталон и итоговое сравнение после восстановления ≥1000px находятся в
+[desktop regression report](../desktop-regression/README.md). Desktop-снимки этого исторического
+mobile-прохода не являются актуальным эталоном desktop.
+
+## Направление и критерии до реализации
+
+Запрос пользователя: устранить 12 проблем на приложенных mobile screenshots. Режим: исправление существующего интерфейса PROCOLLAB. Mont, семантические tokens, текущие иконки, роли, API и бизнес-действия сохраняются. Светлая нейтральная шапка с тёмными иконками явно выбрана пользователем. Существующие ListPage, DetailPage, ProjectList и ParticipantList остаются основой.
+
+Источники качества: `procollab-design-system-v1/docs/design-quality/mobile.md`, `antislop.md`, `patterns.md`, текущие shared-компоненты и screenshots пользователя. Применяются читаемость, группировка, компактная плотность и отсутствие декоративного пересечения иконок/текста. Внешние правила лендингов, шрифтов, иконок Fill и Figma не переносятся в runtime. Порядок блока «Моя активность» меняется по явному пункту 6 пользователя. Новая продуктовая функция и перенос в Figma не входят в задачу.
+
+| AC | Исправление | Приёмка |
+| --- | ----------------------------------------------- | ----------------------------------------------------------------------------------------- |
+| 1 | Заголовок шапки соответствует текущему маршруту | Новости/Профиль не наследуют «Программы», в том числе при переходе внутри приложения |
+| 2 | Категории новостей без выступающих иконок | Иконка, название и счётчик в потоке, без пересечения |
+| 3 | Удалён дублирующий «Фильтр» ленты | Один набор категорий; выбор меняет прежний query/filter и active state |
+| 4 | Полные названия навыков | Перенос строк; дополнительные навыки раскрываются доступной кнопкой |
+| 5 | Компактные карточки проектов | На mobile ширина не растягивается на всю страницу, CTA ≥44 px и внутри карточки |
+| 6 | «Моя активность» выше списка | Полноценный summary по ширине контейнера, метрики 2×2, desktop sidebar сохранён |
+| 7 | Компактные карточки участников | Ограниченная ширина, читаемые имя/специальность/навык, CTA по содержимому |
+| 8 | Программа: география читается полностью | Даты и «для всей России» отдельными строками, без clipping |
+| 9 | Понятные действия программы | Название программы, явно подписанные «Контакты» и «Положение», аккуратная группа действий |
+| 10 | Действия профиля сгруппированы | Ровная сетка, без пустых разделителей и разнесённых по краям одиночных кнопок |
+| 11 | Действия и metadata проекта | Общая сетка действий; metadata занимает всю доступную ширину mobile |
+| 12 | Спокойная шапка с центром | Светлый фон, тёмные иконки, центр заголовка совпадает с центром viewport, цели ≥44 px |
+
+Проверка: 320/360/390/430/768/1440 px, обычный и длинный русский контент, before/after screenshots, переходы внутри приложения, категории и раскрытие навыков, keyboard/focus, применимые loading/disabled/validation состояния. Геометрия не заменяет ручной просмотр всех затронутых экранов. Реальные iOS/Android на dev по-прежнему требуют доступа к устройствам и стенду.
+
+## Итоговая реализация
+
+Светлая шапка использует существующий surface token и симметричные боковые зоны. Заголовок определяется текущим маршрутом при прямом открытии и SPA-переходах, поэтому поздний ответ программы не подменяет «Новости»/«Профиль». Выход доступен в мобильном drawer; уведомления и аватар имеют native controls с областью нажатия ≥44 px.
+
+В ленте остался один работающий набор категорий. Иконка, название и счётчик расположены в потоке. Навыки вакансии используют `VacancySkills` с полными подписями и раскрытием остальных. Проекты и участники используют общий token ширины 260 px до desktop breakpoint; списки размещают столько компактных карточек, сколько помещается. Активность показана над списком, метаданные проекта занимают всю ширину mobile.
+
+Общий `Detail` показывает название и существующую обложку, выравнивает secondary actions в две колонки, убирает пустые divider cells и подписывает «Контакты»/«Положение». Primary action программы расположен первым. В карточке программы даты и география разделены; registration state и его приоритет сохранены. При проверке дополнительно исправлена область пустого snackbar, которая перехватывала клик по аватару на tablet.
+
+Изменены shared-компоненты: `FeedFilter`, `InfoCard`, `VacancySkills`, `Detail`, `ProfileControlPanel`, `ProfileInfo`; shared стили `feed-card`, `ui-tokens`. На страницах изменены `Nav`/`Office`/`Snackbar`, `ProjectActivityCard`, `ProjectsLeftSide`, `ProgramCard`, `MemberCard`, сетки проектов/участников и отступы ленты. Mont, текущие иконки, Button/Card/PageHeader и UIKit adapters сохраняются.
+
+**Бизнес-логика не менялась.** Нет diff в API/domain/infrastructure, routes, permissions, payloads, dependencies или backend. Категории вызывают прежний `FeedFilterInfoService.setFilter`; навыки раскрывает существующий widget; logout вызывает прежний `Office.onLogout`. Условия ролей, сроки регистрации, status precedence, команды, заявки и отправка решений сохранены. Изменения TypeScript ограничены UI title/output/imports и удалением неиспользуемого dropdown UI.
+
+## Проверки и evidence
+
+Среда: Windows, headless Chrome/Playwright, production Angular build, локальный preview, синтетический API. Запросы и мутации не уходят на реальный сервер. В fixtures есть заведомо длинные строки и неполные данные; изображения/имена в evidence не являются реальными данными dev.
+
+| Проверка | Результат | Evidence |
+| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
+| Unit/regression suite | 2006 tests / 406 files PASS | [tests.log](tests.log) |
+| Повтор после последней правки шаблона названия | 41 InfoCard tests PASS | [info-card-tests.log](info-card-tests.log) |
+| Production build | PASS; существующие template/CommonJS warnings | [build.log](build.log) |
+| ESLint | 0 errors, 6 существующих warnings | [lint.log](lint.log) |
+| Stylelint изменённых SCSS | PASS | [styles.log](styles.log) |
+| Prettier, весь repo, Windows end-of-line auto | PASS | [format-all.log](format-all.log) |
+| Геометрия и console errors | 48 экранов на 320/360/390/430/768/1440 px PASS | [after.json](after.json), [browser-check.cjs](browser-check.cjs) |
+| Поведение и touch targets | 18 сценариев на 320/390/768 px PASS; SPA title, query/API filter, skill expansion, layout, Escape/focus | [interactions.json](interactions.json), [interactions.cjs](interactions.cjs) |
+| Разделы и состояния | 48 проверок на 320/390/1440 px PASS; проекты, вакансии, программы, курсы, профиль/edit, onboarding | [states.json](states.json), [state-check.cjs](state-check.cjs) |
+
+Проверка состояний включает задержку ответа и блокировку повторной отправки, empty list, injected HTTP 500 и рабочий retry, disabled button/filter без запроса, validation регистрации/onboarding без мутации. Ожидаемые ошибки injected HTTP 500 отдельно отмечены в JSON. Before screenshots сняты с merged dev `ec57fa7c` до пересборки изменённых исходников; результат: [before.json](before.json).
+
+| Экран, 390 px | До | После |
+| ------------------ | ------------------------------------------------ | ---------------------------------------------- |
+| Новости | [before](screenshots/before/feed-390.png) | [after](screenshots/after/feed-390.png) |
+| Dashboard проектов | [before](screenshots/before/projects-390.png) | [after](screenshots/after/projects-390.png) |
+| Мои проекты | [before](screenshots/before/my-projects-390.png) | [after](screenshots/after/my-projects-390.png) |
+| Участники | [before](screenshots/before/members-390.png) | [after](screenshots/after/members-390.png) |
+| Программы | [before](screenshots/before/programs-390.png) | [after](screenshots/after/programs-390.png) |
+| Программа | [before](screenshots/before/program-390.png) | [after](screenshots/after/program-390.png) |
+| Профиль | [before](screenshots/before/profile-390.png) | [after](screenshots/after/profile-390.png) |
+| Проект | [before](screenshots/before/project-390.png) | [after](screenshots/after/project-390.png) |
+
+## Ограничения и следующий этап
+
+Все 12 пунктов пользователя проверены исходниками, в браузере и визуально; [requirement audit](review.md). Автоматическая геометрия дополнена просмотром ключевых mobile screens, desktop и снимков состояний. Скриншоты, JSON и logs свёрнуты в GitHub diff через `.gitattributes`.
+
+**Not checked:** физические iOS Safari / Android Chrome на dev, реальные аккаунты и screen reader. Browser emulation не подтверждает эти среды и не заменяет запрошенный smoke-test. После merge этого отдельного fix PR нужен smoke-test на dev до prod: открыть все ключевые разделы, выполнить SPA navigation, фильтрацию/раскрытие навыков, проверить drawer/notifications, keyboard в формах и роли программы. Найденные на устройствах проблемы исправлять отдельными PR. Production merge/deploy в эту задачу не входят.
+
+API/data migration не требуются. Визуальные изменения shared компонентов распространяются на их consumers; поэтому перепроверены связанные разделы и состояния. Текущая палитра не объявляется полностью WCAG AA compliant.
diff --git a/docs/mobile-polish/after.json b/docs/mobile-polish/after.json
new file mode 100644
index 000000000..e0ad38261
--- /dev/null
+++ b/docs/mobile-polish/after.json
@@ -0,0 +1,2406 @@
+[
+ {
+ "name": "feed",
+ "width": 320,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 320,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 320,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 320,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 320,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 320,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 320,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 320,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 360,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 360,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 360,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 360,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 360,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 360,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 360,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 360,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 390,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 390,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 390,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 390,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 390,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 390,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 390,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 390,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 430,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 430,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 430,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 430,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 430,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 430,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 430,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 430,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 768,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 768,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 768,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 768,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 768,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 768,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 768,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 768,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 1440,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 1440,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПро",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 1440,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПри",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 1440,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 1440,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026 -",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 1440,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nпроекты-участники\nучастни",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 1440,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 1440,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе",
+ "errors": []
+ }
+]
diff --git a/docs/mobile-polish/before.json b/docs/mobile-polish/before.json
new file mode 100644
index 000000000..7787c80c8
--- /dev/null
+++ b/docs/mobile-polish/before.json
@@ -0,0 +1,2358 @@
+[
+ {
+ "name": "feed",
+ "width": 320,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "все новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nФильтр\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерфе",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 320,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 320,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 320,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 320,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n-\n\n01.01.2027\n\n• для всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 320,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "оценка проектов\nаналитика\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nподробн",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 320,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Алексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинноеНазвани",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 320,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 360,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "все новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nФильтр\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерфе",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 360,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 360,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 360,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 360,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n-\n\n01.01.2027\n\n• для всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 360,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "оценка проектов\nаналитика\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nподробн",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 360,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Алексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинноеНазвани",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 360,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 360,
+ "pageWidth": 360,
+ "bodyWidth": 360,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 390,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "все новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nФильтр\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерфе",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 390,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 390,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 390,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 390,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n-\n\n01.01.2027\n\n• для всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 390,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "оценка проектов\nаналитика\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nподробн",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 390,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Алексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинноеНазвани",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 390,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 430,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "все новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nФильтр\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерфе",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 430,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 430,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 430,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 430,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n-\n\n01.01.2027\n\n• для всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 430,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "оценка проектов\nаналитика\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\n0 / 159",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 430,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Алексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинноеНазвани",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 430,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 430,
+ "pageWidth": 430,
+ "bodyWidth": 430,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 768,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "все новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nФильтр\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерфе",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 768,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 768,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nМоя активность\nПроектов\n1\nЯ лидер\n1\nВ программе\n0\nСд",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 768,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 768,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n-\n\n01.01.2027\n\n• для всей России",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 768,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "оценка проектов\nаналитика\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nподробн",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 768,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Алексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинноеНазвани",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 768,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "errors": []
+ },
+ {
+ "name": "feed",
+ "width": 1440,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости прогр",
+ "errors": []
+ },
+ {
+ "name": "projects",
+ "width": 1440,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПро",
+ "errors": []
+ },
+ {
+ "name": "my-projects",
+ "width": 1440,
+ "actualPath": "/office/projects/my",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-project-activity-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nПри",
+ "errors": []
+ },
+ {
+ "name": "members",
+ "width": 1440,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-member-card",
+ "app-button",
+ "app-members-filters",
+ "app-autocomplete-input",
+ "app-member-statistics-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nучастники\n\nПоиск\n\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело",
+ "errors": []
+ },
+ {
+ "name": "programs",
+ "width": 1440,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nпрограммы\n\nПоиск\n\nКейс-чемпионат студенческих проектов\n\nты уже участвуешь!\n\n01.10.2026\n\n",
+ "errors": []
+ },
+ {
+ "name": "program",
+ "width": 1440,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nоценка проектов\nаналитика\nпроекты-участники\nучастники\nаналитика\nорганизатор\nУчастники\n1\n",
+ "errors": []
+ },
+ {
+ "name": "profile",
+ "width": 1440,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26",
+ "errors": []
+ },
+ {
+ "name": "project",
+ "width": 1440,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nКейс-чемпионат студенческих пр...\n\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАксе",
+ "errors": []
+ }
+]
diff --git a/docs/mobile-polish/browser-check.cjs b/docs/mobile-polish/browser-check.cjs
new file mode 100644
index 000000000..14769150f
--- /dev/null
+++ b/docs/mobile-polish/browser-check.cjs
@@ -0,0 +1,54 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch, measure } = require("../responsive/browser-harness.cjs");
+const fixtures = require("./fixtures.cjs");
+const phase = process.argv[2] || "after";
+const widths = [320, 360, 390, 430, 768, 1440];
+const screens = [
+ ["feed", "/office/feed", "app-open-vacancy"],
+ ["projects", "/office/projects/dashboard", "app-info-card"],
+ ["my-projects", "/office/projects/my", "app-info-card"],
+ ["members", "/office/members", "app-member-card"],
+ ["programs", "/office/program/all", "app-program-card"],
+ ["program", "/office/program/1", "app-detail"],
+ ["profile", "/office/profile/1", "app-detail"],
+ ["project", "/office/projects/1", "app-detail"],
+];
+const directory = path.join(__dirname, "screenshots", phase);
+fs.mkdirSync(directory, { recursive: true });
+(async () => {
+ const rows = [];
+ for (const width of widths) {
+ const h = await launch(width, { isMobile: width < 750, hasTouch: width < 750 });
+ try {
+ for (const [name, route, selector] of screens) {
+ h.errors.length = 0;
+ await h.page.goto(h.base + route);
+ await h.page.waitForLoadState("networkidle");
+ await h.page.locator(selector).first().waitFor({ state: "visible", timeout: 10000 });
+ const measurement = await measure(h.page);
+ await h.page.screenshot({
+ path: path.join(directory, `${name}-${width}.png`),
+ fullPage: true,
+ });
+ if (phase === "after") {
+ assert.equal(measurement.pageWidth <= width + 1, true, `${name} ${width} page overflow`);
+ assert.deepEqual(measurement.overflows, [], `${name} ${width}`);
+ assert.deepEqual(h.errors, [], `${name} ${width}`);
+ }
+ rows.push({ name, width, ...measurement, errors: [...h.errors] });
+ console.log(`${phase}: ${name} ${width}`);
+ }
+ } finally {
+ await h.browser.close();
+ }
+ }
+ fs.writeFileSync(path.join(__dirname, `${phase}.json`), JSON.stringify(rows, null, 2) + "\n");
+ console.log(`${rows.length} ${phase} captures completed`);
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/mobile-polish/browser.log b/docs/mobile-polish/browser.log
new file mode 100644
index 000000000..07d173b08
--- /dev/null
+++ b/docs/mobile-polish/browser.log
@@ -0,0 +1,49 @@
+after: feed 320
+after: projects 320
+after: my-projects 320
+after: members 320
+after: programs 320
+after: program 320
+after: profile 320
+after: project 320
+after: feed 360
+after: projects 360
+after: my-projects 360
+after: members 360
+after: programs 360
+after: program 360
+after: profile 360
+after: project 360
+after: feed 390
+after: projects 390
+after: my-projects 390
+after: members 390
+after: programs 390
+after: program 390
+after: profile 390
+after: project 390
+after: feed 430
+after: projects 430
+after: my-projects 430
+after: members 430
+after: programs 430
+after: program 430
+after: profile 430
+after: project 430
+after: feed 768
+after: projects 768
+after: my-projects 768
+after: members 768
+after: programs 768
+after: program 768
+after: profile 768
+after: project 768
+after: feed 1440
+after: projects 1440
+after: my-projects 1440
+after: members 1440
+after: programs 1440
+after: program 1440
+after: profile 1440
+after: project 1440
+48 after captures completed
diff --git a/docs/mobile-polish/build.log b/docs/mobile-polish/build.log
new file mode 100644
index 000000000..4204a69cf
--- /dev/null
+++ b/docs/mobile-polish/build.log
@@ -0,0 +1,1152 @@
+
+> procollab@0.0.0 build:social:prod
+> npm run build:sprite && ng build social_platform --configuration=production
+
+
+> procollab@0.0.0 build:sprite
+> svg-sprite -s --dest=projects/social_platform/src/assets/icons "projects/social_platform/src/assets/icons/svg/**/*.svg"
+
+> Building...
+√ Building...
+Initial chunk files | Names | Raw size | Estimated transfer size
+chunk-3DFUC4ZD.js | - | 415.14 kB | 72.46 kB
+chunk-EMX2ZQ7G.js | - | 213.04 kB | 60.81 kB
+main-3G3JXXOW.js | main | 207.19 kB | 53.23 kB
+styles-GQ6NWUF3.css | styles | 131.39 kB | 12.03 kB
+chunk-32JCLU4R.js | - | 111.30 kB | 28.30 kB
+chunk-FQQXBL2D.js | - | 83.07 kB | 25.83 kB
+chunk-IQWATLI4.js | - | 73.82 kB | 17.10 kB
+chunk-XZDUNLXR.js | - | 49.83 kB | 10.26 kB
+chunk-SEBII2ES.js | - | 42.79 kB | 8.66 kB
+chunk-LQCFT4Z5.js | - | 28.10 kB | 7.56 kB
+chunk-53SHMX3B.js | - | 26.33 kB | 5.24 kB
+chunk-AGYL4TXQ.js | - | 11.43 kB | 2.59 kB
+chunk-U6SLWTRI.js | - | 9.38 kB | 3.00 kB
+chunk-JL552RI3.js | - | 4.30 kB | 1.19 kB
+chunk-LGEYGYTW.js | - | 4.04 kB | 1.47 kB
+chunk-XZLEJTYL.js | - | 3.19 kB | 1.27 kB
+chunk-JP4HTDU5.js | - | 1.47 kB | 386 bytes
+chunk-VOSPIT4N.js | - | 1.22 kB | 521 bytes
+chunk-UMKP35NR.js | - | 695 bytes | 695 bytes
+chunk-JHUOFMVX.js | - | 483 bytes | 483 bytes
+chunk-ZTXJLEZP.js | - | 474 bytes | 474 bytes
+chunk-IAS7Y3HI.js | - | 465 bytes | 465 bytes
+chunk-4WVOMZ3C.js | - | 352 bytes | 352 bytes
+chunk-Y7FCNQPS.js | - | 195 bytes | 195 bytes
+chunk-RQDRLMC2.js | - | 180 bytes | 180 bytes
+chunk-W2ZPBHP5.js | - | 160 bytes | 160 bytes
+chunk-N7PJCV3T.js | - | 128 bytes | 128 bytes
+chunk-DKVRXEF2.js | - | 127 bytes | 127 bytes
+chunk-PY5GJ2VA.js | - | 51 bytes | 51 bytes
+chunk-GDMD5RKS.js | - | 51 bytes | 51 bytes
+chunk-NCHAAQO5.js | - | 30 bytes | 30 bytes
+chunk-KTRLVWC3.js | - | 30 bytes | 30 bytes
+chunk-CRTRRB5R.js | - | 30 bytes | 30 bytes
+chunk-PKT6RRYE.js | - | 30 bytes | 30 bytes
+chunk-YIJ4Z6S4.js | - | 30 bytes | 30 bytes
+chunk-KEPWQ2XV.js | - | 30 bytes | 30 bytes
+chunk-FE3JRQRM.js | - | 30 bytes | 30 bytes
+chunk-GAELZNYR.js | - | 25 bytes | 25 bytes
+chunk-4CQUPGHG.js | - | 25 bytes | 25 bytes
+chunk-PPZSTFUD.js | - | 25 bytes | 25 bytes
+chunk-UYXSSEQD.js | - | 25 bytes | 25 bytes
+chunk-FI4DW6KU.js | - | 25 bytes | 25 bytes
+chunk-25HWN6II.js | - | 25 bytes | 25 bytes
+chunk-SVFKPVOL.js | - | 25 bytes | 25 bytes
+chunk-CRUTENDI.js | - | 0 bytes | 0 bytes
+chunk-S7EUWH5W.js | - | 0 bytes | 0 bytes
+
+ | Initial total | 1.42 MB | 315.65 kB
+
+Lazy chunk files | Names | Raw size | Estimated transfer size
+chunk-KJV4655H.js | detail-routes | 268.07 kB | 41.83 kB
+chunk-OYEHLSME.js | onboarding-routes | 111.52 kB | 15.02 kB
+chunk-AUN646PD.js | office-routes | 102.43 kB | 19.00 kB
+chunk-GNM5YFID.js | detail-routes | 91.14 kB | 16.82 kB
+chunk-BTMT4Q3X.js | lesson-routes | 82.78 kB | 10.90 kB
+chunk-XY3ULAHD.js | - | 82.17 kB | 16.11 kB
+chunk-TLJCG35F.js | projects-routes | 74.57 kB | 13.85 kB
+chunk-AJJJSWEY.js | index | 72.43 kB | 17.54 kB
+chunk-WLMQT3DH.js | auth-routes | 69.69 kB | 9.69 kB
+chunk-3PWCBJRN.js | - | 66.21 kB | 13.34 kB
+chunk-LWIL3KQZ.js | vacancies-detail-routes | 42.99 kB | 8.81 kB
+chunk-DNRR2I3P.js | project-team-step-component | 40.41 kB | 8.08 kB
+chunk-6V3S7R7B.js | profile-detail-routes | 40.05 kB | 7.65 kB
+chunk-SOJBAKOG.js | course-detail-routes | 39.61 kB | 7.10 kB
+chunk-3UU3AKUA.js | project-main-step-component | 37.06 kB | 7.12 kB
+...and 88 more lazy chunks files. Use "--verbose" to show all the files.
+
+Application bundle generation complete. [20.126 seconds] - 2026-10-04T20:04:35.688Z
+
+▲ [WARNING] 2 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ null
+
+
+▲ [WARNING] NG8113: BackComponent is not used within the template of CoursesComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/courses/courses.component.ts:19:4:
+ 19 │ BackComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: ButtonComponent is not used within the template of CourseComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.ts:32:4:
+ 32 │ ButtonComponent,
+ ╵ ~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: LoaderComponent is not used within the template of CoursesListComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/courses/list/list.component.ts:18:73:
+ 18 │ ...nt, CommonModule, RouterModule, CourseComponent, LoaderComponent],
+ ╵ ~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: IconComponent is not used within the template of FeedComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/feed/feed.component.ts:36:4:
+ 36 │ IconComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:9:67:
+ 9 │ ...card__photo" [url]="member().personal?.avatar || ''" [size]="70" />
+ ╵ ~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:15:66:
+ 15 │ ...er-card__secondary" [title]="member().personal?.speciality || ''">
+ ╵ ~~~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:16:28:
+ 16 │ {{ member().personal?.speciality }}
+ ╵ ~~~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:17:30:
+ 17 │ @if (member().personal?.birthday; as birthday) {
+ ╵ ~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.html:18:30:
+ 18 │ {{ member().personal?.speciality ? " • " : "" }}{{ birth...
+ ╵ ~~~~~~~~~~
+
+ Warning occurs in the template of component MemberCardComponent.
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.ts:16:15:
+ 16 │ templateUrl: "./member-card.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: DialogFooterDirective is not used within the template of MemberFiltersDialogComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/members/member-filters-dialog/member-filters-dialog.component.ts:37:4:
+ 37 │ DialogFooterDirective,
+ ╵ ~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: ProfileInfoComponent is not used within the template of NavComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/office/nav/nav.component.ts:82:4:
+ 82 │ ProfileInfoComponent,
+ ╵ ~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: AlertDirective is not used within the template of SnackbarComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.ts:37:12:
+ 37 │ imports: [AlertDirective, CommonModule, IconComponent],
+ ╵ ~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.html:435:45:
+ 435 │ ... @if (achievements.at(i)?.get("title"); as title) {
+ ╵ ~~~
+
+ Warning occurs in the template of component OnboardingStageZeroComponent.
+
+ projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.ts:23:15:
+ 23 │ templateUrl: "./stage-zero.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8102: The left side of this nullish coalescing operation does not include 'null' or 'undefined' in its type, therefore the '??' operator can be safely removed. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.html:28:15:
+ 28 │ ... {{ user()!.personal.speciality ?? "не указана" }}
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Warning occurs in the template of component ProfileLeftSideComponent.
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.ts:23:15:
+ 23 │ templateUrl: "./profile-left-side.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: TruncatePipe is not used within the template of ProfileLeftSideComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.ts:25:78:
+ 25 │ ...RouterModule, IconComponent, YearsFromBirthdayPipe, TruncatePipe],
+ ╵ ~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: TruncatePipe is not used within the template of ProfileRightSideComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.ts:32:4:
+ 32 │ TruncatePipe,
+ ╵ ~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: UploadFileComponent is not used within the template of ProfileMainStepComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.ts:33:4:
+ 33 │ UploadFileComponent,
+ ╵ ~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html:95:52:
+ 95 │ ... [isSubscribed]="profileProjSubsIds()?.includes(listItem.id)"
+ ╵ ~~~~~~~~
+
+ Warning occurs in the template of component ProgramListComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.ts:40:15:
+ 40 │ templateUrl: "./list.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html:103:54:
+ 103 │ ... [isSubscribed]="profileProjSubsIds()?.includes(listItem.id)"
+ ╵ ~~~~~~~~
+
+ Warning occurs in the template of component ProgramListComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.ts:40:15:
+ 40 │ templateUrl: "./list.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.html:73:64:
+ 73 │ ...)!.isUserMember && program()!.links?.length && program()!.links) {
+ ╵ ~~~~~~
+
+ Warning occurs in the template of component ProgramDetailMainComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.ts:38:15:
+ 38 │ templateUrl: "./main.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.html:82:68:
+ 82 │ ... @if (program()!.isUserMember && program()!.materials?.length) {
+ ╵ ~~~~~~
+
+ Warning occurs in the template of component ProgramDetailMainComponent.
+
+ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.ts:38:15:
+ 38 │ templateUrl: "./main.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: BackComponent is not used within the template of ProgramComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/program/program.component.ts:22:4:
+ 22 │ BackComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: RouterLink is not used within the template of BarNewComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts:11:41:
+ 11 │ ...bsComponent, CommonModule, RouterLink, RouterLinkActive, IconCo...
+ ╵ ~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: RouterLinkActive is not used within the template of BarNewComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts:11:53:
+ 11 │ ...onent, CommonModule, RouterLink, RouterLinkActive, IconComponent],
+ ╵ ~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: IconComponent is not used within the template of BarNewComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts:11:71:
+ 11 │ ...onent, CommonModule, RouterLink, RouterLinkActive, IconComponent],
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: MessageInputComponent is not used within the template of ProjectChatComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/detail/chat/chat.component.ts:34:4:
+ 34 │ MessageInputComponent,
+ ╵ ~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.html:10:39:
+ 10 │ ... @if (achievements.at(i)?.get("title"); as achievementsName) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectAchievementStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.ts:17:15:
+ 17 │ templateUrl: "./project-achievement-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.html:315:32:
+ 315 │ @if (goals.at(i)?.get("title"); as goalName) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectMainStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.ts:39:15:
+ 39 │ templateUrl: "./project-main-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.html:331:32:
+ 331 │ @if (goals.at(i)?.get("completionDate"); as goalDat...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectMainStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.ts:39:15:
+ 39 │ templateUrl: "./project-main-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.html:353:32:
+ 353 │ @if (goals.at(i)?.get("responsible"); as goalLeader) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectMainStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.ts:39:15:
+ 39 │ templateUrl: "./project-main-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: IconComponent is not used within the template of ProjectNavigationComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.ts:25:27:
+ 25 │ imports: [TabsComponent, IconComponent, CommonModule],
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:11:37:
+ 11 │ @if (partners.at(i)?.get("name"); as name) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:27:37:
+ 27 │ @if (partners.at(i)?.get("inn"); as inn) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:46:35:
+ 46 │ ... @if (partners.at(i)?.get("contribution"); as contribut...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:63:35:
+ 63 │ ... @if (partners.at(i)?.get("decisionMaker"); as decision...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:116:36:
+ 116 │ @if (resources.at(i)?.get("type"); as type) {
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:133:36:
+ 133 │ ... @if (resources.at(i)?.get("description"); as descripti...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.html:150:36:
+ 150 │ ... @if (resources.at(i)?.get("partnerCompany"); as partne...
+ ╵ ~~~
+
+ Warning occurs in the template of component ProjectPartnerResourcesStepComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.ts:20:15:
+ 20 │ templateUrl: "./project-partner-resources-step.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8109: isFilterOpen is a function and should be invoked: isFilterOpen() [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/projects.component.html:94:73:
+ 94 │ ...s="filter page__filter" [class.page__filter--open]="isFilterOpen">
+ ╵ ~~~~~~~~~~~~
+
+ Warning occurs in the template of component ProjectsComponent.
+
+ projects/social_platform/src/app/ui/pages/projects/projects.component.ts:30:15:
+ 30 │ templateUrl: "./projects.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: BackComponent is not used within the template of ProjectsComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/projects/projects.component.ts:42:4:
+ 42 │ BackComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-left-side/vacancies-left-side.component.html:7:29:
+ 7 │ @if (item.description?.trim()) {
+ ╵ ~~~~
+
+ Warning occurs in the template of component VacanciesLeftSideComponent.
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-left-side/vacancies-left-side.component.ts:9:15:
+ 9 │ templateUrl: "./vacancies-left-side.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.html:57:23:
+ 57 │ @if (item.project?.links?.length) {
+ ╵ ~~~~~
+
+ Warning occurs in the template of component VacanciesRightSideComponent.
+
+ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.ts:14:15:
+ 14 │ templateUrl: "./vacancies-right-side.component.html",
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: IconComponent is not used within the template of VacanciesListComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/vacancies/list/list.component.ts:30:4:
+ 30 │ IconComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: BackComponent is not used within the template of VacanciesComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/pages/vacancies/vacancies.component.ts:27:4:
+ 27 │ BackComponent,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: RouterLink is not used within the template of BarComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/primitives/bar/bar.component.ts:38:41:
+ 38 │ ...bsComponent, CommonModule, RouterLink, RouterLinkActive, BackCo...
+ ╵ ~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: RouterLinkActive is not used within the template of BarComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/primitives/bar/bar.component.ts:38:53:
+ 38 │ ...onent, CommonModule, RouterLink, RouterLinkActive, BackComponent],
+ ╵ ~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] NG8113: CardDirective is not used within the template of NewsCardComponent [plugin angular-compiler]
+
+ projects/social_platform/src/app/ui/widgets/news-card/news-card.component.ts:58:4:
+ 58 │ CardDirective,
+ ╵ ~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss:121:4:
+ 121 │ margin-top: auto;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss:128:2:
+ 128 │ padding-top: 45px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/detail/team/team.component.scss:19:4:
+ 19 │ row-gap: 48px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss:24:2:
+ 24 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss:56:6:
+ 56 │ + &_arrow {
+ ╵ ^
+
+
+ The selector "+ .field__input-slim:focus_arrow" is invalid CSS.
+ This will be an error in Dart Sass 2.0.0.
+
+ More info: https://sass-lang.com/d/bogus-combinators
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss:59:8:
+ 59 │ i {
+ ╵ ^
+
+
+ The selector "+ .field__input-slim:focus_arrow i" is invalid CSS.
+ This will be an error in Dart Sass 2.0.0.
+
+ More info: https://sass-lang.com/d/bogus-combinators
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:71:8:
+ 71 │ position: sticky;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:72:8:
+ 72 │ bottom: 0;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:73:8:
+ 73 │ z-index: 2;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:74:8:
+ 74 │ justify-content: center;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/modal/modal.component.scss:75:8:
+ 75 │ padding-top: 8px;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss:62:4:
+ 62 │ border-radius: var(--ui-radius-card);
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss:59:4:
+ 59 │ width: 100%;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/ui/src/lib/components/primitives/button/button.component.scss:14:2:
+ 14 │ position: relative;
+ ╵ ^
+
+
+ Sass's behavior for declarations that appear after nested
+ rules will be changing to match the behavior specified by CSS in an upcoming
+ version. To keep the existing behavior, move the declaration above the nested
+ rule. To opt into the new behavior, wrap the declaration in `& {}`.
+
+ More info: https://sass-lang.com/d/mixed-decls
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:9:8:
+ 9 │ @import "styles/colors.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:10:8:
+ 10 │ @import "styles/global.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:11:8:
+ 11 │ @import "styles/responsive.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:12:8:
+ 12 │ @import "styles/rounded.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] Deprecation [plugin angular-sass]
+
+ projects/social_platform/src/styles.scss:13:8:
+ 13 │ @import "styles/typography.scss";
+ ╵ ^
+
+
+ Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
+
+ More info and automated migrator: https://sass-lang.com/d/import
+
+ The plugin "angular-sass" was triggered by this import
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+▲ [WARNING] 11 repetitive deprecation warnings omitted.
+Run in verbose mode to see all warnings. [plugin angular-sass]
+
+ angular:styles/global:styles:1:8:
+ 1 │ @import 'projects/social_platform/src/styles.scss';
+ ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ null
+
+
+▲ [WARNING] bundle initial exceeded maximum budget. Budget 500.00 kB was not met by 920.77 kB with a total of 1.42 MB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/office/office.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.33 kB with a total of 3.33 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-skills-step/profile-skills-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 587 bytes with a total of 2.59 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.40 kB with a total of 3.40 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-achievements-step/profile-achievements-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 410 bytes with a total of 2.41 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.38 kB with a total of 4.38 kB.
+
+
+▲ [WARNING] projects/ui/src/lib/components/primitives/button/button.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 944 bytes with a total of 2.94 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/search/search.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 323 bytes with a total of 2.32 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/list/list.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 519 bytes with a total of 2.52 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/news-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.80 kB with a total of 6.80 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.06 kB with a total of 3.06 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/select/select.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.70 kB with a total of 6.70 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/feed/new-project/new-project.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.28 kB with a total of 3.28 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.75 kB with a total of 6.75 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-education-step/profile-education-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 328 bytes with a total of 2.33 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.37 kB with a total of 6.37 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.25 kB with a total of 3.25 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-three/user-type-card/user-type-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.27 kB with a total of 4.27 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 888 bytes with a total of 2.89 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/carousel/carousel.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.14 kB with a total of 5.14 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.50 kB with a total of 4.50 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/edit.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 7.33 kB with a total of 9.33 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/skills-basket/skills-basket.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.01 kB with a total of 5.01 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/invite-card/invite-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 447 bytes with a total of 2.45 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/file-task/file-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.87 kB with a total of 6.87 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/project-rating.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.37 kB with a total of 4.37 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.04 kB with a total of 7.04 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.24 kB with a total of 4.24 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.63 kB with a total of 6.63 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/tag/tag.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.12 kB with a total of 3.12 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/chat-window/chat-message/chat-message.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.23 kB with a total of 5.23 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 11.24 kB with a total of 13.24 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-experience-step/profile-experience-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 328 bytes with a total of 2.33 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-partner-resources-step/project-partner-resources-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.04 kB with a total of 4.04 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.65 kB with a total of 4.65 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/main/main.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.27 kB with a total of 6.27 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/avatar-control/avatar-control.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 262 bytes with a total of 2.26 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/project-direction-card/project-direction-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.74 kB with a total of 3.74 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 239 bytes with a total of 2.24 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.25 kB with a total of 6.25 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/vacancies/detail/info/info.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.11 kB with a total of 6.11 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-three/stage-three.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.13 kB with a total of 4.13 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/feed-news-preview/feed-news-preview.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.96 kB with a total of 5.96 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.85 kB with a total of 4.85 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/members/members-filters/members-filters.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.15 kB with a total of 4.15 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/lesson.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.28 kB with a total of 5.28 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 6.50 kB with a total of 8.50 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-two/stage-two.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.49 kB with a total of 6.49 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/onboarding/stage-one/stage-one.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.50 kB with a total of 5.50 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/news-card/feed-news-modal/feed-news-modal.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 825 bytes with a total of 2.83 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/project-invite/project-invite-dialog.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 7.79 kB with a total of 9.79 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.19 kB with a total of 4.19 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/complete/complete.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.27 kB with a total of 4.27 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/vacancy-filter/vacancy-filter.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.55 kB with a total of 5.55 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.30 kB with a total of 5.30 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/detail/info/course-module-card/circle-progress-bar/circle-progress-bar.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.08 kB with a total of 4.08 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/message-input/message-input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.54 kB with a total of 6.54 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 6.26 kB with a total of 8.26 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.11 kB with a total of 3.12 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/detail/course-detail.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.42 kB with a total of 5.42 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 8.02 kB with a total of 10.02 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 426 bytes with a total of 2.43 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/info-card/info-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 9.60 kB with a total of 11.60 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/program/detail/list/program-projects-filter/program-projects-filter.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.26 kB with a total of 5.26 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.48 kB with a total of 6.48 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/collaborator-card/collaborator-card.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 447 bytes with a total of 2.45 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/detail/info/info.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.16 kB with a total of 5.16 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/input/input.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 5.90 kB with a total of 7.90 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 1.04 kB with a total of 3.04 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/auth/login/login.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.44 kB with a total of 5.44 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/primitives/tooltip/tooltip.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.80 kB with a total of 5.80 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/courses/courses.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 2.07 kB with a total of 4.07 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/widgets/detail/detail.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 8.08 kB with a total of 10.08 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.77 kB with a total of 5.77 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.22 kB with a total of 6.22 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 4.34 kB with a total of 6.34 kB.
+
+
+▲ [WARNING] projects/social_platform/src/app/ui/pages/auth/register/register.component.scss exceeded maximum budget. Budget 2.00 kB was not met by 3.09 kB with a total of 5.09 kB.
+
+
+▲ [WARNING] Module 'dayjs' used by 'projects/social_platform/src/app/api/auth/facades/ui/auth-ui-info.service.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'snakecase-keys' used by 'projects/core/src/lib/interceptors/camelcase.interceptor.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/plugin/customParseFormat' used by 'projects/core/src/lib/services/validation/validation.service.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/plugin/relativeTime' used by 'projects/core/src/lib/services/validation/validation.service.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/plugin/isToday' used by 'projects/core/src/lib/pipes/formatters/dayjs.pipe.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'dayjs/locale/ru' used by 'projects/core/src/lib/pipes/formatters/dayjs.pipe.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'file-saver' used by 'projects/social_platform/src/app/utils/export-file.ts' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+▲ [WARNING] Module 'map-obj' used by 'node_modules/camelcase-keys/index.js' is not ESM
+
+ CommonJS or AMD dependencies can cause optimization bailouts.
+ For more information see: https://angular.dev/tools/cli/build#configuring-commonjs-dependencies
+
+
+Output location: Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\dist\social_platform
+
diff --git a/docs/mobile-polish/fixtures.cjs b/docs/mobile-polish/fixtures.cjs
new file mode 100644
index 000000000..1ce136e31
--- /dev/null
+++ b/docs/mobile-polish/fixtures.cjs
@@ -0,0 +1,41 @@
+/** @format */
+
+const fixtures = require("../responsive/fixtures.cjs");
+fixtures.user.firstName = "Алексей";
+fixtures.user.lastName = "Куделько";
+fixtures.project.name = "Городские проекты";
+fixtures.project.shortDescription = "Сервис для студенческих команд";
+fixtures.project.region = "Ростовская область";
+fixtures.project.partnerProgram = {
+ id: 1,
+ programId: 1,
+ programLinkId: 1,
+ name: "Акселератор студенческих проектов",
+ isSubmitted: false,
+ canSubmit: true,
+ programFields: [],
+ programFieldValues: [],
+};
+fixtures.program.name = "Кейс-чемпионат студенческих проектов";
+fixtures.vacancy.role = "Дизайнер интерфейсов";
+fixtures.vacancy.description = "Помогите создавать понятные интерфейсы для студенческих команд.";
+fixtures.vacancy.requiredSkills = [
+ "Мотивированность",
+ "Глубинное интервью",
+ "Проектирование пользовательского опыта",
+ "Figma",
+].map((name, id) => ({ id: id + 1, name, category: { id: 1, name: "Soft skills" }, approves: [] }));
+const response = fixtures.response;
+fixtures.response = (pathname, method, query, state) =>
+ /\/feed\/$/.test(pathname)
+ ? {
+ count: 1,
+ next: null,
+ previous: null,
+ counts: { all: 88, project: 56, vacancy: 1, news: 31, partnerprogram: 0, education: 0 },
+ results: [
+ { typeModel: "vacancy", content: fixtures.vacancy, publishedAt: "2026-09-29T12:00:00Z" },
+ ],
+ }
+ : response(pathname, method, query, state);
+module.exports = fixtures;
diff --git a/docs/mobile-polish/format-all.log b/docs/mobile-polish/format-all.log
new file mode 100644
index 000000000..4aa0d16e7
--- /dev/null
+++ b/docs/mobile-polish/format-all.log
@@ -0,0 +1,2 @@
+Checking formatting...
+All matched files use Prettier code style!
diff --git a/docs/mobile-polish/format.log b/docs/mobile-polish/format.log
new file mode 100644
index 000000000..4aa0d16e7
--- /dev/null
+++ b/docs/mobile-polish/format.log
@@ -0,0 +1,2 @@
+Checking formatting...
+All matched files use Prettier code style!
diff --git a/docs/mobile-polish/info-card-tests.log b/docs/mobile-polish/info-card-tests.log
new file mode 100644
index 000000000..c00a8f3a4
--- /dev/null
+++ b/docs/mobile-polish/info-card-tests.log
@@ -0,0 +1,11 @@
+
+ RUN v3.2.6 Z:/Документы/PROCOLLAB-dev/procollab-dev-platform-responsive
+
+ ✓ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.spec.ts (41 tests) 1426ms
+ ✓ InfoCardComponent: статусы моих проектов > 'draft' / 'Лидер': статус, доступ и единственный корректный маршрут 340ms
+
+ Test Files 1 passed (1)
+ Tests 41 passed (41)
+ Start at 22:52:23
+ Duration 10.62s (transform 6.29s, setup 3.01s, collect 4.41s, tests 1.43s, environment 1.27s, prepare 1.47s)
+
diff --git a/docs/mobile-polish/interactions.cjs b/docs/mobile-polish/interactions.cjs
new file mode 100644
index 000000000..75312ccca
--- /dev/null
+++ b/docs/mobile-polish/interactions.cjs
@@ -0,0 +1,184 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch, assertViewport } = require("../responsive/browser-harness.cjs");
+const fixtures = require("./fixtures.cjs");
+const rows = [];
+const directory = path.join(__dirname, "screenshots", "interactions");
+fs.mkdirSync(directory, { recursive: true });
+
+async function goto(h, route, selector) {
+ h.errors.length = 0;
+ await h.page.goto(h.base + route);
+ await h.page.waitForLoadState("networkidle");
+ await h.page.locator(selector).first().waitFor();
+}
+
+async function check(h, name, width, details = {}) {
+ const measurement = await assertViewport(h.page);
+ assert.deepEqual(h.errors, []);
+ const screenshot = `screenshots/interactions/${name}-${width}.png`;
+ await h.page.screenshot({ path: path.join(__dirname, screenshot), fullPage: true });
+ rows.push({ name, width, passed: true, ...details, ...measurement, screenshot });
+ console.log(`${name} ${width}: passed`);
+}
+
+(async () => {
+ for (const width of [320, 390, 768]) {
+ const h = await launch(width, { isMobile: width < 750, hasTouch: width < 750 });
+ h.page.setDefaultTimeout(10000);
+ try {
+ await goto(h, "/office/program/all", "app-program-card");
+ const region = h.page.locator(".card__region").first();
+ assert.equal((await region.textContent()).trim(), "для всей России");
+ assert.ok(await region.evaluate(el => el.scrollWidth <= el.clientWidth + 1));
+ await h.page.getByRole("button", { name: "Открыть меню", exact: true }).click();
+ assert.equal(await h.page.getByRole("button", { name: "Выйти", exact: true }).count(), 1);
+ await h.page.locator("#mobile-navigation a[routerLink=feed]").click();
+ await h.page.locator("app-open-vacancy").waitFor();
+ await h.page.waitForLoadState("networkidle");
+ assert.equal((await h.page.locator(".nav-bar__title").textContent()).trim(), "Новости");
+ const title = await h.page.locator(".nav-bar__title").boundingBox();
+ const header = await h.page.locator(".office__top").boundingBox();
+ assert.ok(Math.abs(title.x + title.width / 2 - header.x - header.width / 2) <= 1);
+ assert.equal(
+ await h.page.locator(".office__top").evaluate(el => getComputedStyle(el).backgroundImage),
+ "none",
+ );
+ for (const selector of [
+ ".nav-bar__toggle",
+ "button.control-panel__action",
+ ".control-panel__profile .user",
+ ]) {
+ const box = await h.page.locator(selector).boundingBox();
+ assert.ok(box.width >= 44 && box.height >= 44, selector + " target");
+ }
+ assert.equal(await h.page.locator("app-feed-filter .filter__option").count(), 6);
+ assert.equal(await h.page.locator("app-feed-filter .select").count(), 0);
+ const notifications = h.page.getByRole("button", { name: "Уведомления", exact: true });
+ await notifications.focus();
+ await h.page.keyboard.press("Enter");
+ await h.page.locator(".control-panel__notifications").waitFor();
+ assert.equal(await notifications.getAttribute("aria-expanded"), "true");
+ await h.page.locator("app-open-vacancy h3").click();
+ await h.page.locator(".control-panel__notifications").waitFor({ state: "detached" });
+ const noOverlap = await h.page
+ .locator("app-feed-filter .filter__option")
+ .evaluateAll(options =>
+ options.every(option => {
+ const icon = option.querySelector(".filter__option--icon").getBoundingClientRect();
+ const label = option.querySelector(".filter__title").getBoundingClientRect();
+ const count = option.querySelector(".filter__count").getBoundingClientRect();
+ return (
+ icon.right <= label.left && (label.bottom <= count.top || label.right <= count.left)
+ );
+ }),
+ );
+ assert.ok(noOverlap);
+ const toggle = h.page.locator("app-open-vacancy .skills__toggle");
+ await toggle.click();
+ await h.page.locator("app-open-vacancy app-tag").nth(3).waitFor();
+ assert.equal(await toggle.getAttribute("aria-expanded"), "true");
+ assert.equal(await h.page.locator("app-open-vacancy app-tag").count(), 4);
+ const skillVisible = await h.page.locator("app-open-vacancy app-tag").evaluateAll(tags =>
+ tags.every(tag => {
+ const el = tag.querySelector("p") || tag;
+ const s = getComputedStyle(el);
+ return s.textOverflow !== "ellipsis" && el.scrollWidth <= el.clientWidth + 1;
+ }),
+ );
+ assert.ok(skillVisible);
+ const category = h.page.locator(".filter__option").filter({ hasText: "свежие вакансии" });
+ await category.click();
+ await h.page.waitForURL(/includes=vacancy/);
+ await h.page.waitForLoadState("networkidle");
+ assert.equal(await category.getAttribute("aria-pressed"), "true");
+ assert.ok(h.requests.some(r => /\/feed\/$/.test(r.path) && /type=vacancy/.test(r.query)));
+ const disabled = h.page.getByRole("button", { name: /образование/ });
+ assert.equal(await disabled.isDisabled(), true);
+ const url = h.page.url();
+ await disabled.evaluate(el => el.click());
+ assert.equal(h.page.url(), url);
+ await check(h, "navigation-feed-skills", width);
+
+ await goto(h, "/office/projects/dashboard", "app-info-card");
+ const activity = await h.page.locator("app-project-activity-card").boundingBox();
+ const list = await h.page.locator(".page__outlet").boundingBox();
+ const parent = await h.page.locator(".page__info").boundingBox();
+ assert.ok(activity.y + activity.height <= list.y + 1);
+ assert.ok(Math.abs(activity.width - parent.width) <= 1);
+ assert.equal(
+ await h.page
+ .locator(".activity__metrics")
+ .evaluate(el => getComputedStyle(el).gridTemplateColumns.split(" ").length),
+ 2,
+ );
+ const card = await h.page.locator("app-info-card .card__body").first().boundingBox();
+ assert.ok(card.width <= 261 && card.width < parent.width);
+ await check(h, "projects-activity", width);
+
+ await goto(h, "/office/members", "app-member-card");
+ const member = await h.page.locator("app-member-card .member-card").first().boundingBox();
+ assert.ok(member.width <= 261);
+ await check(h, "members", width);
+
+ for (const [name, route] of [
+ ["profile", "/office/profile/1"],
+ ["project", "/office/projects/1"],
+ ["program", "/office/program/1"],
+ ]) {
+ await goto(h, route, ".info__actions app-button");
+ const actions = await h.page.locator(".info__actions").boundingBox();
+ const children = await h.page
+ .locator(
+ ".info__actions > a, .info__actions > app-button, .info__actions > .info__unavailable",
+ )
+ .all();
+ for (const child of children) {
+ if (!(await child.isVisible())) continue;
+ const box = await child.boundingBox();
+ assert.ok(Math.abs(box.width - (actions.width - 12) / 2) <= 1, `${name} action column`);
+ const button = child.locator("button").first();
+ const buttonBox = await button.boundingBox();
+ assert.ok(
+ buttonBox.height >= 44 && Math.abs(buttonBox.width - box.width) <= 1,
+ `${name} button target`,
+ );
+ }
+ assert.equal(await h.page.locator(".info__divider:visible").count(), 0);
+ assert.ok((await h.page.locator(".info__page-header").textContent()).trim().length > 0);
+ if (name === "project") {
+ const metadata = await h.page.locator("app-projects-left-side").boundingBox();
+ assert.ok(metadata.width > actions.width - 2, "project metadata full width");
+ }
+ if (name === "program") {
+ const contacts = h.page.getByRole("button", { name: "Контакты", exact: true });
+ assert.equal(await contacts.count(), 1);
+ assert.equal(await contacts.isDisabled(), true);
+ }
+ await check(h, `${name}-actions`, width);
+ }
+ await h.page.getByRole("link", { name: "Мой профиль", exact: true }).click();
+ await h.page.waitForURL(/\/office\/profile\/1$/);
+ await h.page.waitForLoadState("networkidle");
+ assert.equal((await h.page.locator(".nav-bar__title").textContent()).trim(), "Профиль");
+ await h.page.getByRole("button", { name: "Открыть меню", exact: true }).click();
+ await h.page.keyboard.press("Escape");
+ await h.page.locator("#mobile-navigation").waitFor({ state: "detached" });
+ assert.equal(await h.page.locator("#mobile-navigation").count(), 0);
+ assert.equal(
+ await h.page.locator(".nav-bar__toggle").evaluate(el => document.activeElement === el),
+ true,
+ );
+ } finally {
+ await h.browser.close();
+ }
+ }
+ fs.writeFileSync(path.join(__dirname, "interactions.json"), JSON.stringify(rows, null, 2) + "\n");
+ console.log(`${rows.length} interaction screens passed`);
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/mobile-polish/interactions.json b/docs/mobile-polish/interactions.json
new file mode 100644
index 000000000..0ab753dd2
--- /dev/null
+++ b/docs/mobile-polish/interactions.json
@@ -0,0 +1,917 @@
+[
+ {
+ "name": "navigation-feed-skills",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "?includes=vacancy",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "screenshot": "screenshots/interactions/navigation-feed-skills-320.png"
+ },
+ {
+ "name": "projects-activity",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "screenshot": "screenshots/interactions/projects-activity-320.png"
+ },
+ {
+ "name": "members",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "screenshot": "screenshots/interactions/members-320.png"
+ },
+ {
+ "name": "profile-actions",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "screenshot": "screenshots/interactions/profile-actions-320.png"
+ },
+ {
+ "name": "project-actions",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "screenshot": "screenshots/interactions/project-actions-320.png"
+ },
+ {
+ "name": "program-actions",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "screenshot": "screenshots/interactions/program-actions-320.png"
+ },
+ {
+ "name": "navigation-feed-skills",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "?includes=vacancy",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "screenshot": "screenshots/interactions/navigation-feed-skills-390.png"
+ },
+ {
+ "name": "projects-activity",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "screenshot": "screenshots/interactions/projects-activity-390.png"
+ },
+ {
+ "name": "members",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "screenshot": "screenshots/interactions/members-390.png"
+ },
+ {
+ "name": "profile-actions",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "screenshot": "screenshots/interactions/profile-actions-390.png"
+ },
+ {
+ "name": "project-actions",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "screenshot": "screenshots/interactions/project-actions-390.png"
+ },
+ {
+ "name": "program-actions",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "screenshot": "screenshots/interactions/program-actions-390.png"
+ },
+ {
+ "name": "navigation-feed-skills",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "?includes=vacancy",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-open-vacancy",
+ "app-vacancy-skills",
+ "app-tag"
+ ],
+ "text": "Новости\nвсе новости\n88\nновости проектов\n56\nсвежие вакансии\n1\nновости сообщества\n31\nновости программ\n0\nобразование\n0\nНовая вакансия\n29.09.2026\nПроект / компания\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nДизайнер интерф",
+ "screenshot": "screenshots/interactions/navigation-feed-skills-768.png"
+ },
+ {
+ "name": "projects-activity",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/projects/dashboard",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-modal",
+ "app-state",
+ "app-project-activity-card",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-dashboard",
+ "app-dashboard-item",
+ "app-info-card",
+ "app-state",
+ "app-project-activity-card"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\n\nПривязан к программе\n\nГородские проекты\n\nПрограмма: Акселератор студенческих проектов\n\nСервис для студенческих команд\n\nЛидер\n\nможно редактировать\n\nОткрыть\nпоказать раздел\n\nмои подписки\n\nГородские проекты\n\nСервис для студенческих команд\n\nОткрыть\nпок",
+ "screenshot": "screenshots/interactions/projects-activity-768.png"
+ },
+ {
+ "name": "members",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/members",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-members",
+ "app-page-header",
+ "app-back",
+ "app-member-statistics-card",
+ "app-member-card"
+ ],
+ "text": "Участники\nучастники\nФильтры\nПерейти в профиль\nСтатистика\nВсего участников\n—\nВ проектах\n—\nВ программах\n—\nНе удалось загрузить статистику участников\nКандидат\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nРазработчик • 26 л",
+ "screenshot": "screenshots/interactions/members-768.png"
+ },
+ {
+ "name": "profile-actions",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nАлексей Куделько\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nнавыки\n\n0 / 15940\n\n01.10.2026\n\nОченьДлинно",
+ "screenshot": "screenshots/interactions/profile-actions-768.png"
+ },
+ {
+ "name": "project-actions",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/projects/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-card",
+ "app-carousel",
+ "app-projects-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-projects-left-side",
+ "app-projects-mid-side",
+ "app-news-form",
+ "app-textarea",
+ "app-project-direction-card",
+ "app-news-card",
+ "app-projects-right-side"
+ ],
+ "text": "Профиль проекта\nГородские проекты\nрабочая зона\nчат проекта\nкоманда\nредактировать\nосновное\nПрограмма\nАкселератор студенческих проектов\nСфера\n\nИнформационные технологии\n\nРегион\n\nРостовская область\n\nTRL\n\n1\n\nСрок реализации\n\n2027-01-01\n\nЛидер\nТестовый ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "screenshot": "screenshots/interactions/project-actions-768.png"
+ },
+ {
+ "name": "program-actions",
+ "width": 768,
+ "passed": true,
+ "actualPath": "/office/program/1",
+ "actualQuery": "",
+ "viewport": 768,
+ "pageWidth": 753,
+ "bodyWidth": 753,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-main",
+ "app-program-role-widget",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card"
+ ],
+ "text": "Программы\nКейс-чемпионат студенческих проектов\nоценка проектов\nаналитика\nКонтакты\nпроекты-участники\nучастники\nматериалы\nаналитика\nорганизатор\nУчастники\n1\nПроекты\n1\nСдано\nрешений\n0\nБез проектов\n0\n0,0%\nОткрыть →\nо программе\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНаз",
+ "screenshot": "screenshots/interactions/program-actions-768.png"
+ }
+]
diff --git a/docs/mobile-polish/interactions.log b/docs/mobile-polish/interactions.log
new file mode 100644
index 000000000..d7b0bd150
--- /dev/null
+++ b/docs/mobile-polish/interactions.log
@@ -0,0 +1,19 @@
+navigation-feed-skills 320: passed
+projects-activity 320: passed
+members 320: passed
+profile-actions 320: passed
+project-actions 320: passed
+program-actions 320: passed
+navigation-feed-skills 390: passed
+projects-activity 390: passed
+members 390: passed
+profile-actions 390: passed
+project-actions 390: passed
+program-actions 390: passed
+navigation-feed-skills 768: passed
+projects-activity 768: passed
+members 768: passed
+profile-actions 768: passed
+project-actions 768: passed
+program-actions 768: passed
+18 interaction screens passed
diff --git a/docs/mobile-polish/lint.log b/docs/mobile-polish/lint.log
new file mode 100644
index 000000000..9008d29f4
--- /dev/null
+++ b/docs/mobile-polish/lint.log
@@ -0,0 +1,20 @@
+
+> procollab@0.0.0 lint:ts
+> eslint projects/**/*.ts
+
+
+Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\projects\core\src\lib\services\logger\logger.service.ts
+ 47:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+ 61:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+ 73:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+ 85:3 warning Unused eslint-disable directive (no problems were reported from 'no-console')
+
+Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\projects\social_platform\src\app\domain\chat\chat-message.model.ts
+ 22:3 warning Unused eslint-disable directive (no problems were reported from 'no-use-before-define')
+
+Z:\Документы\PROCOLLAB-dev\procollab-dev-platform-responsive\projects\social_platform\src\app\ui\widgets\message-input\message-input.component.ts
+ 176:3 warning Unused eslint-disable directive (no problems were reported from 'no-use-before-define')
+
+✖ 6 problems (0 errors, 6 warnings)
+ 0 errors and 6 warnings potentially fixable with the `--fix` option.
+
diff --git a/docs/mobile-polish/review.md b/docs/mobile-polish/review.md
new file mode 100644
index 000000000..479f37b7b
--- /dev/null
+++ b/docs/mobile-polish/review.md
@@ -0,0 +1,32 @@
+
+
+# Requirement audit и review
+
+Base: `origin/dev` / `ec57fa7cadb8ca7acef6859380a966a837783495` (merged PR #401). Head: `fix/dev-mobile-ui-composition`. Scope: 12 замечаний пользователя и выбранная им светлая шапка. Review выполнен в текущей задаче по `procollab-review`, PR оформлен по `procollab-pr`; отдельный агент не использовался.
+
+| AC | Реализация | Evidence | Verdict |
+| --- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------- |
+| 1 | `Nav.routeTitle`, initial URL, NavigationEnd + защита от позднего navTitle | Прямое открытие ленты/профиля; program → feed → profile SPA | PASS |
+| 2 | `FeedFilter` grid, static icon | Проверка непересечения icon/label/count, screenshots 320/390 | PASS |
+| 3 | Удалён dropdown; прежний `setFilter` | Один набор 6 категорий, includes=vacancy и API type=vacancy, disabled education | PASS |
+| 4 | Общий `VacancySkills`, переносы | Видимость полного текста; native expand, все 4 навыка; unit integration | PASS |
+| 5 | `InfoCard`, grids, token 260 px | Измерение ширины и visual dashboard/my/projects | PASS |
+| 6 | `Projects` responsive order, `ProjectActivityCard` 2×2 | Activity выше outlet, полная ширина контейнера; desktop screenshot | PASS |
+| 7 | `MemberCard`, `Members` grid | Ширина ≤260, навык переносится, CTA внутри; visual + overflow | PASS |
+| 8 | `ProgramCard` avatar 64, dates/region отдельно | Полная строка geography, scrollWidth≤clientWidth, 6 widths | PASS |
+| 9 | Общий `Detail`, PageHeader, подписанные контакты/положение | Program screenshot, native disabled contacts, равные secondary columns | PASS |
+| 10 | `Detail` action grid без divider cells | Profile buttons геометрия и visual 320/390 | PASS |
+| 11 | `Detail` + `ProjectsLeftSide` width | Project actions и metadata: полная mobile width | PASS |
+| 12 | `Office`/`Nav` symmetric grid + surface | Центры title/header совпадают, neutral background, 44 px targets, Escape/focus | PASS |
+
+Checked by source: просмотрен diff относительно dev; call chains setFilter/logout/contacts/materials/roles сохранены. Нет изменений защищённых бизнес-слоёв/API. Существующий wrapper Button и директивы UIKit остаются canonical; новый card/control implementation не добавлен. Shared consumers проверены через экранные и state сценарии. Desktop sidebar и ограничения ролей сохранены.
+
+Checked by tests/build: 2006 regression tests, повтор 41 InfoCard tests после изменения textContent, production build, ESLint, Stylelint, Prettier. Полные команды/логи в [README](README.md).
+
+Checked in browser: 48 geometry screens + 18 interaction scenarios + 48 section/state checks. Просмотрены mobile list/detail/feed screens на 320/390 px, tablet projects и desktop, а также loading/empty/error/validation screenshots. Читаемость проверена на длинных строках; поля/кнопки не уходят за viewport. Навигация использует native keyboard controls и drawer focus return. Метрики активности не интерактивные, их CSS order не добавляет tab stops.
+
+Во время review исправлены пустой заголовок при первом открытии, слишком тесные категории на 320 px, intrinsic width вложенных action buttons и перехват клика пустым snackbar на tablet. Пробелы шаблона InfoCard и асинхронное ожидание DOM в проверках исправлены; итоговые прогоны успешные. Незакрытых BLOCKER/MAJOR в рамках указанных 12 AC нет.
+
+Not checked: реальные устройства/аккаунты dev, screen reader, полное WCAG соответствие. Эти ограничения явно перечислены в PR. Smoke-test на физических iOS/Android выполняется после merge в dev перед prod; он не отмечен пройденным.
+
+Verdict: готово к review и merge в dev после завершённых локальных проверок; production acceptance остаётся отдельным этапом.
diff --git a/docs/mobile-polish/screenshots/after/feed-1440.png b/docs/mobile-polish/screenshots/after/feed-1440.png
new file mode 100644
index 000000000..8a36187be
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/feed-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/feed-320.png b/docs/mobile-polish/screenshots/after/feed-320.png
new file mode 100644
index 000000000..c408ae762
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/feed-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/feed-360.png b/docs/mobile-polish/screenshots/after/feed-360.png
new file mode 100644
index 000000000..f66ed0d7a
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/feed-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/feed-390.png b/docs/mobile-polish/screenshots/after/feed-390.png
new file mode 100644
index 000000000..bc1e6810b
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/feed-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/feed-430.png b/docs/mobile-polish/screenshots/after/feed-430.png
new file mode 100644
index 000000000..1f5fab453
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/feed-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/feed-768.png b/docs/mobile-polish/screenshots/after/feed-768.png
new file mode 100644
index 000000000..ca58289fd
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/feed-768.png differ
diff --git a/docs/mobile-polish/screenshots/after/members-1440.png b/docs/mobile-polish/screenshots/after/members-1440.png
new file mode 100644
index 000000000..217bd49d2
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/members-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/members-320.png b/docs/mobile-polish/screenshots/after/members-320.png
new file mode 100644
index 000000000..a2d5c15a9
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/members-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/members-360.png b/docs/mobile-polish/screenshots/after/members-360.png
new file mode 100644
index 000000000..3f808e1e4
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/members-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/members-390.png b/docs/mobile-polish/screenshots/after/members-390.png
new file mode 100644
index 000000000..006cc3b44
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/members-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/members-430.png b/docs/mobile-polish/screenshots/after/members-430.png
new file mode 100644
index 000000000..7657927b6
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/members-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/members-768.png b/docs/mobile-polish/screenshots/after/members-768.png
new file mode 100644
index 000000000..3f2af2700
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/members-768.png differ
diff --git a/docs/mobile-polish/screenshots/after/my-projects-1440.png b/docs/mobile-polish/screenshots/after/my-projects-1440.png
new file mode 100644
index 000000000..a8cab8d1b
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/my-projects-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/my-projects-320.png b/docs/mobile-polish/screenshots/after/my-projects-320.png
new file mode 100644
index 000000000..0eb539b2f
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/my-projects-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/my-projects-360.png b/docs/mobile-polish/screenshots/after/my-projects-360.png
new file mode 100644
index 000000000..4e8592c31
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/my-projects-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/my-projects-390.png b/docs/mobile-polish/screenshots/after/my-projects-390.png
new file mode 100644
index 000000000..fdf04c57e
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/my-projects-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/my-projects-430.png b/docs/mobile-polish/screenshots/after/my-projects-430.png
new file mode 100644
index 000000000..b2e5420ac
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/my-projects-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/my-projects-768.png b/docs/mobile-polish/screenshots/after/my-projects-768.png
new file mode 100644
index 000000000..e8b7c1c01
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/my-projects-768.png differ
diff --git a/docs/mobile-polish/screenshots/after/profile-1440.png b/docs/mobile-polish/screenshots/after/profile-1440.png
new file mode 100644
index 000000000..2a1cd12c5
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/profile-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/profile-320.png b/docs/mobile-polish/screenshots/after/profile-320.png
new file mode 100644
index 000000000..6d986bb01
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/profile-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/profile-360.png b/docs/mobile-polish/screenshots/after/profile-360.png
new file mode 100644
index 000000000..355c914c9
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/profile-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/profile-390.png b/docs/mobile-polish/screenshots/after/profile-390.png
new file mode 100644
index 000000000..3dc0eef00
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/profile-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/profile-430.png b/docs/mobile-polish/screenshots/after/profile-430.png
new file mode 100644
index 000000000..addfd2d3d
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/profile-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/profile-768.png b/docs/mobile-polish/screenshots/after/profile-768.png
new file mode 100644
index 000000000..2792b9133
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/profile-768.png differ
diff --git a/docs/mobile-polish/screenshots/after/program-1440.png b/docs/mobile-polish/screenshots/after/program-1440.png
new file mode 100644
index 000000000..2d6178c3c
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/program-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/program-320.png b/docs/mobile-polish/screenshots/after/program-320.png
new file mode 100644
index 000000000..d227b6fc7
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/program-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/program-360.png b/docs/mobile-polish/screenshots/after/program-360.png
new file mode 100644
index 000000000..f7b560fcc
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/program-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/program-390.png b/docs/mobile-polish/screenshots/after/program-390.png
new file mode 100644
index 000000000..ca42ebed2
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/program-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/program-430.png b/docs/mobile-polish/screenshots/after/program-430.png
new file mode 100644
index 000000000..94e495336
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/program-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/program-768.png b/docs/mobile-polish/screenshots/after/program-768.png
new file mode 100644
index 000000000..6eb899bf8
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/program-768.png differ
diff --git a/docs/mobile-polish/screenshots/after/programs-1440.png b/docs/mobile-polish/screenshots/after/programs-1440.png
new file mode 100644
index 000000000..c0c1ebedc
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/programs-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/programs-320.png b/docs/mobile-polish/screenshots/after/programs-320.png
new file mode 100644
index 000000000..e64443230
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/programs-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/programs-360.png b/docs/mobile-polish/screenshots/after/programs-360.png
new file mode 100644
index 000000000..4fa7e5b55
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/programs-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/programs-390.png b/docs/mobile-polish/screenshots/after/programs-390.png
new file mode 100644
index 000000000..a5e1daef3
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/programs-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/programs-430.png b/docs/mobile-polish/screenshots/after/programs-430.png
new file mode 100644
index 000000000..0f104efa7
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/programs-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/programs-768.png b/docs/mobile-polish/screenshots/after/programs-768.png
new file mode 100644
index 000000000..d5d7f64fe
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/programs-768.png differ
diff --git a/docs/mobile-polish/screenshots/after/project-1440.png b/docs/mobile-polish/screenshots/after/project-1440.png
new file mode 100644
index 000000000..4d9c55831
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/project-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/project-320.png b/docs/mobile-polish/screenshots/after/project-320.png
new file mode 100644
index 000000000..270a2d0b3
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/project-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/project-360.png b/docs/mobile-polish/screenshots/after/project-360.png
new file mode 100644
index 000000000..fc3e97427
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/project-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/project-390.png b/docs/mobile-polish/screenshots/after/project-390.png
new file mode 100644
index 000000000..28c978850
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/project-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/project-430.png b/docs/mobile-polish/screenshots/after/project-430.png
new file mode 100644
index 000000000..8e6be2380
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/project-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/project-768.png b/docs/mobile-polish/screenshots/after/project-768.png
new file mode 100644
index 000000000..4b4882ef2
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/project-768.png differ
diff --git a/docs/mobile-polish/screenshots/after/projects-1440.png b/docs/mobile-polish/screenshots/after/projects-1440.png
new file mode 100644
index 000000000..69aac292a
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/projects-1440.png differ
diff --git a/docs/mobile-polish/screenshots/after/projects-320.png b/docs/mobile-polish/screenshots/after/projects-320.png
new file mode 100644
index 000000000..2bae40960
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/projects-320.png differ
diff --git a/docs/mobile-polish/screenshots/after/projects-360.png b/docs/mobile-polish/screenshots/after/projects-360.png
new file mode 100644
index 000000000..bb98a90f1
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/projects-360.png differ
diff --git a/docs/mobile-polish/screenshots/after/projects-390.png b/docs/mobile-polish/screenshots/after/projects-390.png
new file mode 100644
index 000000000..e45c85ef0
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/projects-390.png differ
diff --git a/docs/mobile-polish/screenshots/after/projects-430.png b/docs/mobile-polish/screenshots/after/projects-430.png
new file mode 100644
index 000000000..c8c36d8a5
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/projects-430.png differ
diff --git a/docs/mobile-polish/screenshots/after/projects-768.png b/docs/mobile-polish/screenshots/after/projects-768.png
new file mode 100644
index 000000000..52815ac85
Binary files /dev/null and b/docs/mobile-polish/screenshots/after/projects-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/feed-1440.png b/docs/mobile-polish/screenshots/before/feed-1440.png
new file mode 100644
index 000000000..a6fb109dc
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/feed-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/feed-320.png b/docs/mobile-polish/screenshots/before/feed-320.png
new file mode 100644
index 000000000..d3f6881f9
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/feed-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/feed-360.png b/docs/mobile-polish/screenshots/before/feed-360.png
new file mode 100644
index 000000000..462ebc2c9
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/feed-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/feed-390.png b/docs/mobile-polish/screenshots/before/feed-390.png
new file mode 100644
index 000000000..24ba3c1a4
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/feed-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/feed-430.png b/docs/mobile-polish/screenshots/before/feed-430.png
new file mode 100644
index 000000000..b2c1afd7b
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/feed-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/feed-768.png b/docs/mobile-polish/screenshots/before/feed-768.png
new file mode 100644
index 000000000..7d88c3cc6
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/feed-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/members-1440.png b/docs/mobile-polish/screenshots/before/members-1440.png
new file mode 100644
index 000000000..8ea904960
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/members-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/members-320.png b/docs/mobile-polish/screenshots/before/members-320.png
new file mode 100644
index 000000000..904dadfc6
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/members-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/members-360.png b/docs/mobile-polish/screenshots/before/members-360.png
new file mode 100644
index 000000000..960d461c9
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/members-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/members-390.png b/docs/mobile-polish/screenshots/before/members-390.png
new file mode 100644
index 000000000..405c60394
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/members-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/members-430.png b/docs/mobile-polish/screenshots/before/members-430.png
new file mode 100644
index 000000000..063e20049
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/members-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/members-768.png b/docs/mobile-polish/screenshots/before/members-768.png
new file mode 100644
index 000000000..f96fb9a69
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/members-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/my-projects-1440.png b/docs/mobile-polish/screenshots/before/my-projects-1440.png
new file mode 100644
index 000000000..34757b044
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/my-projects-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/my-projects-320.png b/docs/mobile-polish/screenshots/before/my-projects-320.png
new file mode 100644
index 000000000..845e80252
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/my-projects-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/my-projects-360.png b/docs/mobile-polish/screenshots/before/my-projects-360.png
new file mode 100644
index 000000000..4c0d782e5
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/my-projects-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/my-projects-390.png b/docs/mobile-polish/screenshots/before/my-projects-390.png
new file mode 100644
index 000000000..796ff7b13
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/my-projects-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/my-projects-430.png b/docs/mobile-polish/screenshots/before/my-projects-430.png
new file mode 100644
index 000000000..35ac02fc7
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/my-projects-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/my-projects-768.png b/docs/mobile-polish/screenshots/before/my-projects-768.png
new file mode 100644
index 000000000..00fe2231a
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/my-projects-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/profile-1440.png b/docs/mobile-polish/screenshots/before/profile-1440.png
new file mode 100644
index 000000000..c8c34f4ce
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/profile-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/profile-320.png b/docs/mobile-polish/screenshots/before/profile-320.png
new file mode 100644
index 000000000..2def8ec93
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/profile-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/profile-360.png b/docs/mobile-polish/screenshots/before/profile-360.png
new file mode 100644
index 000000000..74a74b3ed
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/profile-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/profile-390.png b/docs/mobile-polish/screenshots/before/profile-390.png
new file mode 100644
index 000000000..db102f671
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/profile-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/profile-430.png b/docs/mobile-polish/screenshots/before/profile-430.png
new file mode 100644
index 000000000..2a8d696ac
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/profile-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/profile-768.png b/docs/mobile-polish/screenshots/before/profile-768.png
new file mode 100644
index 000000000..f9af8d033
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/profile-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/program-1440.png b/docs/mobile-polish/screenshots/before/program-1440.png
new file mode 100644
index 000000000..8a80a80c2
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/program-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/program-320.png b/docs/mobile-polish/screenshots/before/program-320.png
new file mode 100644
index 000000000..731b071dc
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/program-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/program-360.png b/docs/mobile-polish/screenshots/before/program-360.png
new file mode 100644
index 000000000..fde57a1de
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/program-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/program-390.png b/docs/mobile-polish/screenshots/before/program-390.png
new file mode 100644
index 000000000..683da9423
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/program-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/program-430.png b/docs/mobile-polish/screenshots/before/program-430.png
new file mode 100644
index 000000000..c1c1ca2c0
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/program-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/program-768.png b/docs/mobile-polish/screenshots/before/program-768.png
new file mode 100644
index 000000000..e80edd7f2
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/program-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/programs-1440.png b/docs/mobile-polish/screenshots/before/programs-1440.png
new file mode 100644
index 000000000..731a92362
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/programs-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/programs-320.png b/docs/mobile-polish/screenshots/before/programs-320.png
new file mode 100644
index 000000000..3a3558d82
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/programs-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/programs-360.png b/docs/mobile-polish/screenshots/before/programs-360.png
new file mode 100644
index 000000000..748997b3e
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/programs-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/programs-390.png b/docs/mobile-polish/screenshots/before/programs-390.png
new file mode 100644
index 000000000..1cb98cc56
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/programs-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/programs-430.png b/docs/mobile-polish/screenshots/before/programs-430.png
new file mode 100644
index 000000000..f6d577e49
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/programs-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/programs-768.png b/docs/mobile-polish/screenshots/before/programs-768.png
new file mode 100644
index 000000000..8da9cdd2d
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/programs-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/project-1440.png b/docs/mobile-polish/screenshots/before/project-1440.png
new file mode 100644
index 000000000..f4a62eae7
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/project-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/project-320.png b/docs/mobile-polish/screenshots/before/project-320.png
new file mode 100644
index 000000000..56d49a9aa
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/project-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/project-360.png b/docs/mobile-polish/screenshots/before/project-360.png
new file mode 100644
index 000000000..b2ca47e61
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/project-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/project-390.png b/docs/mobile-polish/screenshots/before/project-390.png
new file mode 100644
index 000000000..4c591e7d3
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/project-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/project-430.png b/docs/mobile-polish/screenshots/before/project-430.png
new file mode 100644
index 000000000..4fc49dade
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/project-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/project-768.png b/docs/mobile-polish/screenshots/before/project-768.png
new file mode 100644
index 000000000..1e11621b2
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/project-768.png differ
diff --git a/docs/mobile-polish/screenshots/before/projects-1440.png b/docs/mobile-polish/screenshots/before/projects-1440.png
new file mode 100644
index 000000000..ac4f2fdda
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/projects-1440.png differ
diff --git a/docs/mobile-polish/screenshots/before/projects-320.png b/docs/mobile-polish/screenshots/before/projects-320.png
new file mode 100644
index 000000000..9c9d6c08c
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/projects-320.png differ
diff --git a/docs/mobile-polish/screenshots/before/projects-360.png b/docs/mobile-polish/screenshots/before/projects-360.png
new file mode 100644
index 000000000..7f1ec4816
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/projects-360.png differ
diff --git a/docs/mobile-polish/screenshots/before/projects-390.png b/docs/mobile-polish/screenshots/before/projects-390.png
new file mode 100644
index 000000000..65a3365a9
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/projects-390.png differ
diff --git a/docs/mobile-polish/screenshots/before/projects-430.png b/docs/mobile-polish/screenshots/before/projects-430.png
new file mode 100644
index 000000000..e759f1907
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/projects-430.png differ
diff --git a/docs/mobile-polish/screenshots/before/projects-768.png b/docs/mobile-polish/screenshots/before/projects-768.png
new file mode 100644
index 000000000..679447f54
Binary files /dev/null and b/docs/mobile-polish/screenshots/before/projects-768.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/members-320.png b/docs/mobile-polish/screenshots/interactions/members-320.png
new file mode 100644
index 000000000..a2d5c15a9
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/members-320.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/members-390.png b/docs/mobile-polish/screenshots/interactions/members-390.png
new file mode 100644
index 000000000..006cc3b44
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/members-390.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/members-768.png b/docs/mobile-polish/screenshots/interactions/members-768.png
new file mode 100644
index 000000000..3f2af2700
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/members-768.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-320.png b/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-320.png
new file mode 100644
index 000000000..460708115
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-320.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-390.png b/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-390.png
new file mode 100644
index 000000000..020a0578c
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-390.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-768.png b/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-768.png
new file mode 100644
index 000000000..27b430248
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/navigation-feed-skills-768.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/profile-actions-320.png b/docs/mobile-polish/screenshots/interactions/profile-actions-320.png
new file mode 100644
index 000000000..6d986bb01
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/profile-actions-320.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/profile-actions-390.png b/docs/mobile-polish/screenshots/interactions/profile-actions-390.png
new file mode 100644
index 000000000..3dc0eef00
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/profile-actions-390.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/profile-actions-768.png b/docs/mobile-polish/screenshots/interactions/profile-actions-768.png
new file mode 100644
index 000000000..2792b9133
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/profile-actions-768.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/program-actions-320.png b/docs/mobile-polish/screenshots/interactions/program-actions-320.png
new file mode 100644
index 000000000..d227b6fc7
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/program-actions-320.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/program-actions-390.png b/docs/mobile-polish/screenshots/interactions/program-actions-390.png
new file mode 100644
index 000000000..ca42ebed2
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/program-actions-390.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/program-actions-768.png b/docs/mobile-polish/screenshots/interactions/program-actions-768.png
new file mode 100644
index 000000000..6eb899bf8
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/program-actions-768.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/project-actions-320.png b/docs/mobile-polish/screenshots/interactions/project-actions-320.png
new file mode 100644
index 000000000..270a2d0b3
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/project-actions-320.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/project-actions-390.png b/docs/mobile-polish/screenshots/interactions/project-actions-390.png
new file mode 100644
index 000000000..28c978850
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/project-actions-390.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/project-actions-768.png b/docs/mobile-polish/screenshots/interactions/project-actions-768.png
new file mode 100644
index 000000000..4b4882ef2
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/project-actions-768.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/projects-activity-320.png b/docs/mobile-polish/screenshots/interactions/projects-activity-320.png
new file mode 100644
index 000000000..2bae40960
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/projects-activity-320.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/projects-activity-390.png b/docs/mobile-polish/screenshots/interactions/projects-activity-390.png
new file mode 100644
index 000000000..e45c85ef0
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/projects-activity-390.png differ
diff --git a/docs/mobile-polish/screenshots/interactions/projects-activity-768.png b/docs/mobile-polish/screenshots/interactions/projects-activity-768.png
new file mode 100644
index 000000000..52815ac85
Binary files /dev/null and b/docs/mobile-polish/screenshots/interactions/projects-activity-768.png differ
diff --git a/docs/mobile-polish/screenshots/states/courses-1440.png b/docs/mobile-polish/screenshots/states/courses-1440.png
new file mode 100644
index 000000000..7a8c99b6c
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/courses-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/courses-320.png b/docs/mobile-polish/screenshots/states/courses-320.png
new file mode 100644
index 000000000..c03bda60e
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/courses-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/courses-390.png b/docs/mobile-polish/screenshots/states/courses-390.png
new file mode 100644
index 000000000..9313fe831
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/courses-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/disabled-action-1440.png b/docs/mobile-polish/screenshots/states/disabled-action-1440.png
new file mode 100644
index 000000000..2bc228551
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/disabled-action-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/disabled-action-320.png b/docs/mobile-polish/screenshots/states/disabled-action-320.png
new file mode 100644
index 000000000..f92508267
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/disabled-action-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/disabled-action-390.png b/docs/mobile-polish/screenshots/states/disabled-action-390.png
new file mode 100644
index 000000000..4e9054b07
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/disabled-action-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/disabled-filter-1440.png b/docs/mobile-polish/screenshots/states/disabled-filter-1440.png
new file mode 100644
index 000000000..3a9e481f3
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/disabled-filter-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/disabled-filter-320.png b/docs/mobile-polish/screenshots/states/disabled-filter-320.png
new file mode 100644
index 000000000..9c2c2d7d1
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/disabled-filter-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/disabled-filter-390.png b/docs/mobile-polish/screenshots/states/disabled-filter-390.png
new file mode 100644
index 000000000..184878e47
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/disabled-filter-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/empty-1440.png b/docs/mobile-polish/screenshots/states/empty-1440.png
new file mode 100644
index 000000000..7933c1ef1
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/empty-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/empty-320.png b/docs/mobile-polish/screenshots/states/empty-320.png
new file mode 100644
index 000000000..93d132e62
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/empty-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/empty-390.png b/docs/mobile-polish/screenshots/states/empty-390.png
new file mode 100644
index 000000000..b593e4018
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/empty-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/error-1440.png b/docs/mobile-polish/screenshots/states/error-1440.png
new file mode 100644
index 000000000..a34f54ac8
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/error-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/error-320.png b/docs/mobile-polish/screenshots/states/error-320.png
new file mode 100644
index 000000000..cdba1f904
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/error-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/error-390.png b/docs/mobile-polish/screenshots/states/error-390.png
new file mode 100644
index 000000000..052424d60
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/error-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/loading-action-1440.png b/docs/mobile-polish/screenshots/states/loading-action-1440.png
new file mode 100644
index 000000000..ba30a696f
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/loading-action-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/loading-action-320.png b/docs/mobile-polish/screenshots/states/loading-action-320.png
new file mode 100644
index 000000000..e16222a52
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/loading-action-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/loading-action-390.png b/docs/mobile-polish/screenshots/states/loading-action-390.png
new file mode 100644
index 000000000..bbaba2f18
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/loading-action-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/loading-page-1440.png b/docs/mobile-polish/screenshots/states/loading-page-1440.png
new file mode 100644
index 000000000..c9dcc8a80
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/loading-page-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/loading-page-320.png b/docs/mobile-polish/screenshots/states/loading-page-320.png
new file mode 100644
index 000000000..2f60a1c52
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/loading-page-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/loading-page-390.png b/docs/mobile-polish/screenshots/states/loading-page-390.png
new file mode 100644
index 000000000..e39bf362e
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/loading-page-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/onboarding-0-1440.png b/docs/mobile-polish/screenshots/states/onboarding-0-1440.png
new file mode 100644
index 000000000..66e1d9c09
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/onboarding-0-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/onboarding-0-320.png b/docs/mobile-polish/screenshots/states/onboarding-0-320.png
new file mode 100644
index 000000000..36dd2eeaa
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/onboarding-0-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/onboarding-0-390.png b/docs/mobile-polish/screenshots/states/onboarding-0-390.png
new file mode 100644
index 000000000..3b81d2e46
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/onboarding-0-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/onboarding-1-1440.png b/docs/mobile-polish/screenshots/states/onboarding-1-1440.png
new file mode 100644
index 000000000..adf775ba1
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/onboarding-1-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/onboarding-1-320.png b/docs/mobile-polish/screenshots/states/onboarding-1-320.png
new file mode 100644
index 000000000..f0e2ed53a
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/onboarding-1-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/onboarding-1-390.png b/docs/mobile-polish/screenshots/states/onboarding-1-390.png
new file mode 100644
index 000000000..cc03fb3c6
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/onboarding-1-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/profile-1440.png b/docs/mobile-polish/screenshots/states/profile-1440.png
new file mode 100644
index 000000000..39fcdf376
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/profile-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/profile-320.png b/docs/mobile-polish/screenshots/states/profile-320.png
new file mode 100644
index 000000000..3007d338d
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/profile-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/profile-390.png b/docs/mobile-polish/screenshots/states/profile-390.png
new file mode 100644
index 000000000..23a1958f6
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/profile-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/profile-edit-1440.png b/docs/mobile-polish/screenshots/states/profile-edit-1440.png
new file mode 100644
index 000000000..5d6dab113
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/profile-edit-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/profile-edit-320.png b/docs/mobile-polish/screenshots/states/profile-edit-320.png
new file mode 100644
index 000000000..3c7c46269
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/profile-edit-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/profile-edit-390.png b/docs/mobile-polish/screenshots/states/profile-edit-390.png
new file mode 100644
index 000000000..0dde9893b
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/profile-edit-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/programs-1440.png b/docs/mobile-polish/screenshots/states/programs-1440.png
new file mode 100644
index 000000000..86dc00093
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/programs-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/programs-320.png b/docs/mobile-polish/screenshots/states/programs-320.png
new file mode 100644
index 000000000..d7f61925a
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/programs-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/programs-390.png b/docs/mobile-polish/screenshots/states/programs-390.png
new file mode 100644
index 000000000..d8f937994
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/programs-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/projects-1440.png b/docs/mobile-polish/screenshots/states/projects-1440.png
new file mode 100644
index 000000000..3ba7a67f2
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/projects-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/projects-320.png b/docs/mobile-polish/screenshots/states/projects-320.png
new file mode 100644
index 000000000..3dcc89602
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/projects-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/projects-390.png b/docs/mobile-polish/screenshots/states/projects-390.png
new file mode 100644
index 000000000..7dd67c6df
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/projects-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/vacancies-1440.png b/docs/mobile-polish/screenshots/states/vacancies-1440.png
new file mode 100644
index 000000000..3b95c8404
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/vacancies-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/vacancies-320.png b/docs/mobile-polish/screenshots/states/vacancies-320.png
new file mode 100644
index 000000000..3f179ca86
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/vacancies-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/vacancies-390.png b/docs/mobile-polish/screenshots/states/vacancies-390.png
new file mode 100644
index 000000000..a5e64f193
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/vacancies-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/validation-onboarding-1440.png b/docs/mobile-polish/screenshots/states/validation-onboarding-1440.png
new file mode 100644
index 000000000..5c79cbb15
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/validation-onboarding-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/validation-onboarding-320.png b/docs/mobile-polish/screenshots/states/validation-onboarding-320.png
new file mode 100644
index 000000000..c71b8915e
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/validation-onboarding-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/validation-onboarding-390.png b/docs/mobile-polish/screenshots/states/validation-onboarding-390.png
new file mode 100644
index 000000000..09e965491
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/validation-onboarding-390.png differ
diff --git a/docs/mobile-polish/screenshots/states/validation-register-1440.png b/docs/mobile-polish/screenshots/states/validation-register-1440.png
new file mode 100644
index 000000000..c333b9391
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/validation-register-1440.png differ
diff --git a/docs/mobile-polish/screenshots/states/validation-register-320.png b/docs/mobile-polish/screenshots/states/validation-register-320.png
new file mode 100644
index 000000000..d1d03bd33
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/validation-register-320.png differ
diff --git a/docs/mobile-polish/screenshots/states/validation-register-390.png b/docs/mobile-polish/screenshots/states/validation-register-390.png
new file mode 100644
index 000000000..fada82004
Binary files /dev/null and b/docs/mobile-polish/screenshots/states/validation-register-390.png differ
diff --git a/docs/mobile-polish/state-check.cjs b/docs/mobile-polish/state-check.cjs
new file mode 100644
index 000000000..ee89df52f
--- /dev/null
+++ b/docs/mobile-polish/state-check.cjs
@@ -0,0 +1,232 @@
+/** @format */
+
+const fs = require("node:fs");
+const path = require("node:path");
+const assert = require("node:assert/strict");
+const { launch, assertViewport } = require("../responsive/browser-harness.cjs");
+const fixtures = require("../responsive/fixtures.cjs");
+
+const directory = path.join(__dirname, "screenshots", "states");
+fs.mkdirSync(directory, { recursive: true });
+const rows = [];
+const widths = [320, 390, 1440];
+const sections = [
+ ["projects", "/office/projects/all", "app-info-card"],
+ ["vacancies", "/office/vacancies/all", "app-project-vacancy-card"],
+ ["programs", "/office/program/all", "app-program-card"],
+ ["courses", "/office/courses/all", "app-course"],
+ ["profile", "/office/profile/1", "app-detail"],
+ ["profile-edit", "/office/profile/edit?editingStep=main", "app-page-header"],
+ [
+ "onboarding-0",
+ "/office/onboarding/stage-0",
+ "app-stage-zero .page__form input:not([type=file])",
+ ],
+ ["onboarding-1", "/office/onboarding/stage-1", "app-stage-one app-autocomplete-input"],
+];
+
+async function goto(page, route, settled = true) {
+ await page.goto("http://127.0.0.1:4360" + route);
+ if (settled) await page.waitForLoadState("networkidle");
+}
+
+async function capture(harness, name, width, extra = {}) {
+ const measurement = await assertViewport(harness.page);
+ const expectedErrors = extra.injectedHttp500
+ ? harness.errors.filter(
+ message =>
+ /Failed to load resource.*500/.test(message) ||
+ /\[ERROR\] \[HTTP\] GET https:\/\/(?:api|dev)\.procollab\.ru\/programs\/1\/manager-overview\/ 500 /.test(
+ message,
+ ),
+ )
+ : [];
+ assert.deepEqual(
+ harness.errors.filter(message => !expectedErrors.includes(message)),
+ [],
+ );
+ const screenshot = `screenshots/states/${name}-${width}.png`;
+ await harness.page.screenshot({ path: path.join(__dirname, screenshot), fullPage: true });
+ rows.push({ name, width, passed: true, ...measurement, screenshot, expectedErrors, ...extra });
+ console.log(JSON.stringify({ name, width, passed: true }));
+}
+
+async function state(width, name, action) {
+ const harness = await launch(width, { isMobile: width < 750, hasTouch: width < 750 });
+ harness.page.setDefaultTimeout(8000);
+ try {
+ await action(harness);
+ } finally {
+ await harness.browser.close();
+ }
+}
+
+(async () => {
+ for (const width of widths) {
+ const harness = await launch(width, { isMobile: width < 750, hasTouch: width < 750 });
+ try {
+ for (const [name, route, content] of sections) {
+ harness.errors.length = 0;
+ await goto(harness.page, route);
+ await harness.page.locator(content).first().waitFor({ state: "visible" });
+ await capture(harness, name, width, { category: "section" });
+ }
+ } finally {
+ await harness.browser.close();
+ }
+
+ await state(width, "loading-page", async h => {
+ let release;
+ const pending = new Promise(resolve => {
+ release = resolve;
+ });
+ await h.context.route("**/programs/1/manager-overview/**", async route => {
+ await pending;
+ const url = new URL(route.request().url());
+ await route.fulfill({ json: fixtures.response(url.pathname, "GET", url.searchParams) });
+ });
+ try {
+ await goto(h.page, "/office/program/1/analytics", false);
+ await h.page.getByTestId("analytics-loading").waitFor();
+ await capture(h, "loading-page", width, { category: "loading" });
+ } finally {
+ release();
+ }
+ await h.page.getByTestId("analytics-loading").waitFor({ state: "hidden" });
+ });
+
+ await state(width, "loading-action", async h => {
+ await goto(h.page, "/office/courses/1/lesson/1");
+ await h.page.locator("app-write-task textarea").fill("Ответ для финальной проверки UI Kit");
+ let release;
+ const pending = new Promise(resolve => {
+ release = resolve;
+ });
+ let submissions = 0;
+ await h.context.route("**/courses/tasks/1/answer/", async route => {
+ submissions++;
+ await pending;
+ const url = new URL(route.request().url());
+ await route.fulfill({ json: fixtures.response(url.pathname, "POST", url.searchParams) });
+ });
+ try {
+ const button = h.page.getByRole("button", { name: "завершить урок", exact: true });
+ await button.click();
+ await h.page.locator("app-button app-loader").waitFor();
+ assert.equal(await button.isDisabled(), true);
+ assert.equal(await button.getAttribute("aria-busy"), "true");
+ await button.evaluate(element => element.click());
+ assert.equal(submissions, 1, "Loading must prevent duplicate submission");
+ await capture(h, "loading-action", width, { category: "loading", submissions });
+ } finally {
+ release();
+ }
+ await h.page.locator("app-complete").waitFor();
+ });
+
+ await state(width, "empty", async h => {
+ await h.context.route(
+ url => /\/vacancies\/$/.test(url.pathname),
+ route => route.fulfill({ json: { count: 0, results: [], next: null, previous: null } }),
+ );
+ await goto(h.page, "/office/vacancies/all");
+ await h.page.locator("app-state").getByText("Вакансии не найдены", { exact: true }).waitFor();
+ await capture(h, "empty", width, { category: "empty" });
+ });
+
+ await state(width, "error", async h => {
+ let failing = true;
+ let attempts = 0;
+ await h.context.route("**/programs/1/manager-overview/**", async route => {
+ attempts++;
+ if (failing) return route.fulfill({ status: 500, json: { detail: "Injected QA failure" } });
+ const url = new URL(route.request().url());
+ return route.fulfill({ json: fixtures.response(url.pathname, "GET", url.searchParams) });
+ });
+ await goto(h.page, "/office/program/1/analytics");
+ await h.page.getByTestId("analytics-error").waitFor({ timeout: 60000 });
+ assert.equal(await h.page.getByTestId("analytics-error").getAttribute("role"), "alert");
+ await capture(h, "error", width, { category: "error", injectedHttp500: true });
+ failing = false;
+ await h.page.getByRole("button", { name: "Повторить", exact: true }).click();
+ await h.page.getByTestId("analytics-error").waitFor({ state: "hidden" });
+ await h.page.locator(".summary-card").first().waitFor();
+ assert.ok(attempts >= 2, "Error retry must reload data");
+ await assertViewport(h.page);
+ rows.at(-1).retryPassed = true;
+ });
+
+ await state(width, "disabled-action", async h => {
+ await goto(h.page, "/office/courses/1/lesson/1");
+ const button = h.page.getByRole("button", { name: "завершить урок", exact: true });
+ assert.equal(await button.isDisabled(), true);
+ const before = h.requests.filter(request => request.method !== "GET").length;
+ await button.evaluate(element => element.click());
+ assert.equal(h.requests.filter(request => request.method !== "GET").length, before);
+ assert.equal(
+ await button.evaluate(element => {
+ element.focus();
+ return document.activeElement !== element;
+ }),
+ true,
+ );
+ await capture(h, "disabled-action", width, { category: "disabled" });
+ });
+
+ await state(width, "disabled-filter", async h => {
+ await goto(h.page, "/office/feed");
+ const button = h.page.getByRole("button", { name: /образование/ });
+ assert.equal(await button.isDisabled(), true);
+ const before = h.page.url();
+ await button.evaluate(element => element.click());
+ assert.equal(h.page.url(), before);
+ await capture(h, "disabled-filter", width, { category: "disabled" });
+ });
+
+ await state(width, "validation-register", async h => {
+ await goto(h.page, "/auth/register");
+ if (width >= 1000) {
+ const register = await h.page.locator(".register").boundingBox();
+ assert.ok(register.x >= 199, "Registration must retain the desktop auth gutter");
+ }
+ for (const checkbox of await h.page.locator("app-checkbox .field").all())
+ await checkbox.click();
+ await h.page.getByRole("button", { name: "зарегистрироваться", exact: true }).click();
+ await h.page.locator(".error").first().waitFor();
+ assert.equal(
+ h.requests.some(
+ request => request.method === "POST" && /\/auth\/users\/$/.test(request.path),
+ ),
+ false,
+ );
+ await capture(h, "validation-register", width, { category: "validation" });
+ });
+
+ const avatar = fixtures.user.avatar;
+ fixtures.user.avatar = null;
+ try {
+ await state(width, "validation-onboarding", async h => {
+ await goto(h.page, "/office/onboarding/stage-0");
+ await h.page.getByRole("button", { name: "продолжить", exact: true }).click();
+ await h.page.locator(".error").first().waitFor();
+ assert.equal(h.page.url().includes("stage-0"), true);
+ assert.equal(
+ h.requests.some(request => request.method === "PATCH"),
+ false,
+ );
+ await capture(h, "validation-onboarding", width, { category: "validation" });
+ });
+ } finally {
+ fixtures.user.avatar = avatar;
+ }
+ }
+ assert.equal(rows.length, 48);
+ fs.writeFileSync(
+ path.join(__dirname, "states.json"),
+ JSON.stringify({ widths, rows }, null, 2) + "\n",
+ );
+ console.log(`${rows.length} UI state checks passed`);
+})().catch(error => {
+ console.error(error);
+ process.exitCode = 1;
+});
diff --git a/docs/mobile-polish/states.json b/docs/mobile-polish/states.json
new file mode 100644
index 000000000..0ed1dcf11
--- /dev/null
+++ b/docs/mobile-polish/states.json
@@ -0,0 +1,2336 @@
+{
+ "widths": [320, 390, 1440],
+ "rows": [
+ {
+ "name": "projects",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/projects/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-projects-filter",
+ "app-select",
+ "app-dropdown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-projects-filter",
+ "app-select"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\nФильтр\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nПроект для проверки адаптива\n\nОткрыть\n\nфильтры\n\nсбросить\nсфера проекта",
+ "screenshot": "screenshots/states/projects-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "vacancies",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело",
+ "screenshot": "screenshots/states/vacancies-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "programs",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "screenshot": "screenshots/states/programs-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "courses",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение",
+ "screenshot": "screenshots/states/courses-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвание",
+ "screenshot": "screenshots/states/profile-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile-edit",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон",
+ "screenshot": "screenshots/states/profile-edit-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-0",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nРегион*\n\nОбразование\n\nУровень образования\nВысшее образова",
+ "screenshot": "screenshots/states/onboarding-0-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-1",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group"
+ ],
+ "text": "1\n2\n3\n4\nКем хотите работать?\nзакончить регистрацию позже\nпродолжить\nпоиск по библиотеке\nбиблиотека\nРазработчик",
+ "screenshot": "screenshots/states/onboarding-1-320.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "loading-page",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nЗагружаем аналитику программы…",
+ "screenshot": "screenshots/states/loading-page-320.png",
+ "expectedErrors": [],
+ "category": "loading"
+ },
+ {
+ "name": "loading-action",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n35 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/loading-action-320.png",
+ "expectedErrors": [],
+ "category": "loading",
+ "submissions": 1
+ },
+ {
+ "name": "empty",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nВакансии не найдены\n\nПопробуйте изменить запрос или сбросить фильтры.\n\nСбросить фильтры\nфильтры\nмои отклики",
+ "screenshot": "screenshots/states/empty-320.png",
+ "expectedErrors": [],
+ "category": "empty"
+ },
+ {
+ "name": "error",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nАналитика недоступна\n\nНе удалось загрузить аналитику. ",
+ "screenshot": "screenshots/states/error-320.png",
+ "expectedErrors": [
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:06:35.412] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 55ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:06:37.419] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 4ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:06:41.425] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 4ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:06:49.431] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 4ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\""
+ ],
+ "category": "error",
+ "injectedHttp500": true,
+ "retryPassed": true
+ },
+ {
+ "name": "disabled-action",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n0 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/disabled-action-320.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "disabled-filter",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-state",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-state"
+ ],
+ "text": "Новости\nвсе новости\n0\nновости проектов\n0\nсвежие вакансии\n0\nновости сообщества\n0\nновости программ\n0\nобразование\n0\n\nв данном разделе пока нет новостей",
+ "screenshot": "screenshots/states/disabled-filter-320.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "validation-register",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/auth/register",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button",
+ "app-modal",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button"
+ ],
+ "text": "имя\nфамилия\nдата рождения\nпочта\nпароль\nповторите пароль\nОбязательное поле\nя прочитал соглашение и даю согласие на обработку персональных данных\nнажимая на кнопку подтверждаете, что вам больше 14 лет\nзарегистрироваться\n\nесли есть аккаунт? - войдите",
+ "screenshot": "screenshots/states/validation-register-320.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "validation-onboarding",
+ "width": 320,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 320,
+ "pageWidth": 320,
+ "bodyWidth": 320,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nВыберите фото для профиля\nРегион*\n\nОбразование\n\nУровень о",
+ "screenshot": "screenshots/states/validation-onboarding-320.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "projects",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/projects/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-projects-filter",
+ "app-select",
+ "app-dropdown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-projects-filter",
+ "app-select"
+ ],
+ "text": "Проекты\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\nФильтр\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nПроект для проверки адаптива\n\nОткрыть\n\nфильтры\n\nсбросить\nсфера проекта",
+ "screenshot": "screenshots/states/projects-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "vacancies",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nПроект\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробело",
+ "screenshot": "screenshots/states/vacancies-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "programs",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card"
+ ],
+ "text": "Программы\nпрограммы\n\nПоиск\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nты уже участвуешь!\n\n01.10.2026 - 01.01.2027\n\nдля всей России",
+ "screenshot": "screenshots/states/programs-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "courses",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge"
+ ],
+ "text": "Курсы\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвани...\n\n01.01.2026 — 01.01.2027\n\nпродолжить обучение",
+ "screenshot": "screenshots/states/courses-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "Профиль\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый\nподелиться профилем\nмои проекты\ncкачать CV\nредактировать\nметаданные\n\n26 лет\n\nМосква\n\nРазработчик\n\nобо мне\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазвание",
+ "screenshot": "screenshots/states/profile-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile-edit",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "Редактирование профиля\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nдействия\nфото\nимя\nфамилия\nРегион\nдата рождения\nспециальность\nобо мне\n\n124 / 300\n\nуказать личные контакты\nдобавить контакт\nтелефон",
+ "screenshot": "screenshots/states/profile-edit-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-0",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nРегион*\n\nОбразование\n\nУровень образования\nВысшее образова",
+ "screenshot": "screenshots/states/onboarding-0-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-1",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group"
+ ],
+ "text": "1\n2\n3\n4\nКем хотите работать?\nзакончить регистрацию позже\nпродолжить\nпоиск по библиотеке\nбиблиотека\nРазработчик",
+ "screenshot": "screenshots/states/onboarding-1-390.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "loading-page",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nЗагружаем аналитику программы…",
+ "screenshot": "screenshots/states/loading-page-390.png",
+ "expectedErrors": [],
+ "category": "loading"
+ },
+ {
+ "name": "loading-action",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n35 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/loading-action-390.png",
+ "expectedErrors": [],
+ "category": "loading",
+ "submissions": 1
+ },
+ {
+ "name": "empty",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter"
+ ],
+ "text": "Вакансии\nвакансии\n\nПоиск\n\nВакансии не найдены\n\nПопробуйте изменить запрос или сбросить фильтры.\n\nСбросить фильтры\nфильтры\nмои отклики",
+ "screenshot": "screenshots/states/empty-390.png",
+ "expectedErrors": [],
+ "category": "empty"
+ },
+ {
+ "name": "error",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-modal",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "Программы\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\nназад\nКонтакты\n\nУправление программой\n\nАналитика\n\nСводка пути участников от регистрации до экспертной оценки.\n\nАналитика недоступна\n\nНе удалось загрузить аналитику. ",
+ "screenshot": "screenshots/states/error-390.png",
+ "expectedErrors": [
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:07:12.519] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 44ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:07:14.527] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:07:18.539] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 7ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:07:26.548] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\""
+ ],
+ "category": "error",
+ "injectedHttp500": true,
+ "retryPassed": true
+ },
+ {
+ "name": "disabled-action",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task"
+ ],
+ "text": "Курсы\nназад\n\nмодуль 1\n\nурок 1\n\nо курсе\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазван...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов\n\nответ\n\n0 / 1000\n\nзавершить урок",
+ "screenshot": "screenshots/states/disabled-action-390.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "disabled-filter",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-state",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-avatar",
+ "app-feed",
+ "app-feed-filter",
+ "app-state"
+ ],
+ "text": "Новости\nвсе новости\n0\nновости проектов\n0\nсвежие вакансии\n0\nновости сообщества\n0\nновости программ\n0\nобразование\n0\n\nв данном разделе пока нет новостей",
+ "screenshot": "screenshots/states/disabled-filter-390.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "validation-register",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/auth/register",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button",
+ "app-modal",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button"
+ ],
+ "text": "имя\nфамилия\nдата рождения\nпочта\nпароль\nповторите пароль\nОбязательное поле\nя прочитал соглашение и даю согласие на обработку персональных данных\nнажимая на кнопку подтверждаете, что вам больше 14 лет\nзарегистрироваться\n\nесли есть аккаунт? - войдите",
+ "screenshot": "screenshots/states/validation-register-390.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "validation-onboarding",
+ "width": 390,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 390,
+ "pageWidth": 390,
+ "bodyWidth": 390,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\n2\n3\n4\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nВыберите фото для профиля\nРегион*\n\nОбразование\n\nУровень о",
+ "screenshot": "screenshots/states/validation-onboarding-390.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "projects",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/projects/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-modal",
+ "app-projects-filter",
+ "app-select",
+ "app-dropdown",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-projects",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-search",
+ "app-bar-new",
+ "app-tabs",
+ "app-list",
+ "app-info-card",
+ "app-projects-filter",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nпроекты\nсоздать проект\n\nПоиск\n\nмои проекты\nмои подписки\nмои приглашения\nвсе проекты\n\nОче",
+ "screenshot": "screenshots/states/projects-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "vacancies",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-project-vacancy-card",
+ "app-vacancy-status",
+ "app-badge",
+ "app-vacancy-skills",
+ "app-tag",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nвакансии\n\nПоиск\n\nАктивна\n01.10.2026\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБ",
+ "screenshot": "screenshots/states/vacancies-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "programs",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/program/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-program",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-main",
+ "app-program-card",
+ "app-checkbox",
+ "app-select"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nпрограммы\n\nПоиск\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДли",
+ "screenshot": "screenshots/states/programs-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "courses",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/courses/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-track-career",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-list",
+ "app-course",
+ "app-badge",
+ "app-soon-card",
+ "app-button"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nкурсы\n\nПоиск\n\nдоступно всем пользователям\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНа",
+ "screenshot": "screenshots/states/courses-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/profile/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-modal",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-carousel",
+ "app-profile-right-side",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-profile-main",
+ "app-profile-left-side",
+ "app-profile-mid-side",
+ "app-project-direction-card",
+ "app-news-form",
+ "app-textarea",
+ "app-news-card",
+ "app-profile-right-side"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро",
+ "screenshot": "screenshots/states/profile-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "profile-edit",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/profile/edit",
+ "actualQuery": "?editingStep=main",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-modal",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-profile-edit",
+ "app-page-header",
+ "app-back",
+ "app-button",
+ "app-project-navigation",
+ "app-tabs",
+ "app-profile-main-step",
+ "app-avatar-control",
+ "app-input",
+ "app-region-select",
+ "app-autocomplete-input",
+ "app-textarea"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nредактирование профиля\ncохранить\nосновные данные\nобразование\nработа\nдостижения\nнавыки\nде",
+ "screenshot": "screenshots/states/profile-edit-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-0",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\nОсновные данные\n2\nСпециальность\n3\nНавыки\n4\nТип аккаунта\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nРегион*",
+ "screenshot": "screenshots/states/onboarding-0-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "onboarding-1",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-one",
+ "app-tooltip",
+ "app-button",
+ "app-autocomplete-input",
+ "app-specializations-group"
+ ],
+ "text": "1\nОсновные данные\n2\nСпециальность\n3\nНавыки\n4\nТип аккаунта\nКем хотите работать?\nзакончить регистрацию позже\nпродолжить\nпоиск по библиотеке\nбиблиотека\nРазработчик",
+ "screenshot": "screenshots/states/onboarding-1-1440.png",
+ "expectedErrors": [],
+ "category": "section"
+ },
+ {
+ "name": "loading-page",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро",
+ "screenshot": "screenshots/states/loading-page-1440.png",
+ "expectedErrors": [],
+ "category": "loading"
+ },
+ {
+ "name": "loading-action",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-loader"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nназад\nвернуться в программу\n\nмодуль 1\n\nурок 1\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПроб",
+ "screenshot": "screenshots/states/loading-action-1440.png",
+ "expectedErrors": [],
+ "category": "loading",
+ "submissions": 1
+ },
+ {
+ "name": "empty",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/vacancies/all",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-vacancies",
+ "app-page-header",
+ "app-back",
+ "app-search",
+ "app-vacancies-list",
+ "app-state",
+ "app-button",
+ "app-vacancy-filter",
+ "app-checkbox"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nвакансии\n\nПоиск\n\nВакансии не найдены\n\nПопробуйте изменить запрос или сбросить фильтры.\n\n",
+ "screenshot": "screenshots/states/empty-1440.png",
+ "expectedErrors": [],
+ "category": "empty"
+ },
+ {
+ "name": "error",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/program/1/analytics",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics",
+ "app-analytics-drilldown",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-detail",
+ "app-page-header",
+ "app-button",
+ "app-program-analytics"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПро",
+ "screenshot": "screenshots/states/error-1440.png",
+ "expectedErrors": [
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:07:49.507] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 46ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:07:51.513] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:07:55.520] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\"",
+ "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
+ "[23:08:03.527] [ERROR] [HTTP] GET https://api.procollab.ru/programs/1/manager-overview/ 500 3ms \"Http failure response for https://api.procollab.ru/programs/1/manager-overview/: 500 Internal Server Error\""
+ ],
+ "category": "error",
+ "injectedHttp500": true,
+ "retryPassed": true
+ },
+ {
+ "name": "disabled-action",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/courses/1/lesson/1",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-course-detail",
+ "app-button",
+ "app-lesson",
+ "app-write-task"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nназад\nвернуться в программу\n\nмодуль 1\n\nурок 1\n\n1\n\nзадание 1\n\nОченьДлинноеНазваниеБезПроб",
+ "screenshot": "screenshots/states/disabled-action-1440.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "disabled-filter",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/feed",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-nav",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-state",
+ "app-modal",
+ "app-delete-confirm",
+ "app-snackbar",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-office",
+ "app-program-sidebar-card",
+ "app-avatar",
+ "app-profile-control-panel",
+ "app-profile-info",
+ "app-feed",
+ "app-feed-filter",
+ "app-state"
+ ],
+ "text": "мой профиль\nновости\nпроекты\nучастники\nпрограммы\nвакансии\nкурсы\n\nПлатформа создана компанией ООО «Молодежный форсайт»\n\nПолитика обработки персональных данных\n\n2026\n\nдо 01.01.27\n\nОченьДлинноеНазваниеБезПробело...\n\nвсе новости\n0\nновости проектов\n0\nсвежие вакансии\n0\nновости сообщества\n0\nновости программ",
+ "screenshot": "screenshots/states/disabled-filter-1440.png",
+ "expectedErrors": [],
+ "category": "disabled"
+ },
+ {
+ "name": "validation-register",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/auth/register",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button",
+ "app-modal",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-auth",
+ "app-login",
+ "app-input",
+ "app-checkbox",
+ "app-button"
+ ],
+ "text": "имя\nфамилия\nдата рождения\nпочта\nпароль\nповторите пароль\nОбязательное поле\nя прочитал соглашение и даю согласие на обработку персональных данных\nнажимая на кнопку подтверждаете, что вам больше 14 лет\nзарегистрироваться\n\nесли есть аккаунт? - войдите",
+ "screenshot": "screenshots/states/validation-register-1440.png",
+ "expectedErrors": [],
+ "category": "validation"
+ },
+ {
+ "name": "validation-onboarding",
+ "width": 1440,
+ "passed": true,
+ "actualPath": "/office/onboarding/stage-0",
+ "actualQuery": "",
+ "viewport": 1440,
+ "pageWidth": 1425,
+ "bodyWidth": 1425,
+ "overflows": [],
+ "rendered": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-modal",
+ "app-region-select",
+ "app-select",
+ "app-dropdown",
+ "app-input",
+ "app-button",
+ "app-cookie-consent"
+ ],
+ "visibleApps": [
+ "app-root",
+ "app-onboarding",
+ "app-stage-zero",
+ "app-tooltip",
+ "app-avatar-control",
+ "app-region-select",
+ "app-select",
+ "app-input",
+ "app-button"
+ ],
+ "text": "1\nОсновные данные\n2\nСпециальность\n3\nНавыки\n4\nТип аккаунта\nПривет, ОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробеловОченьДлинноеНазваниеБезПробелов Тестовый! ✌️\n\nРасскажите о себе, чтобы ваше резюме было сильным и отражало опыт\n\nФотография профиля*\n\nВыберит",
+ "screenshot": "screenshots/states/validation-onboarding-1440.png",
+ "expectedErrors": [],
+ "category": "validation"
+ }
+ ]
+}
diff --git a/docs/mobile-polish/states.log b/docs/mobile-polish/states.log
new file mode 100644
index 000000000..a003b8544
--- /dev/null
+++ b/docs/mobile-polish/states.log
@@ -0,0 +1,49 @@
+{"name":"projects","width":320,"passed":true}
+{"name":"vacancies","width":320,"passed":true}
+{"name":"programs","width":320,"passed":true}
+{"name":"courses","width":320,"passed":true}
+{"name":"profile","width":320,"passed":true}
+{"name":"profile-edit","width":320,"passed":true}
+{"name":"onboarding-0","width":320,"passed":true}
+{"name":"onboarding-1","width":320,"passed":true}
+{"name":"loading-page","width":320,"passed":true}
+{"name":"loading-action","width":320,"passed":true}
+{"name":"empty","width":320,"passed":true}
+{"name":"error","width":320,"passed":true}
+{"name":"disabled-action","width":320,"passed":true}
+{"name":"disabled-filter","width":320,"passed":true}
+{"name":"validation-register","width":320,"passed":true}
+{"name":"validation-onboarding","width":320,"passed":true}
+{"name":"projects","width":390,"passed":true}
+{"name":"vacancies","width":390,"passed":true}
+{"name":"programs","width":390,"passed":true}
+{"name":"courses","width":390,"passed":true}
+{"name":"profile","width":390,"passed":true}
+{"name":"profile-edit","width":390,"passed":true}
+{"name":"onboarding-0","width":390,"passed":true}
+{"name":"onboarding-1","width":390,"passed":true}
+{"name":"loading-page","width":390,"passed":true}
+{"name":"loading-action","width":390,"passed":true}
+{"name":"empty","width":390,"passed":true}
+{"name":"error","width":390,"passed":true}
+{"name":"disabled-action","width":390,"passed":true}
+{"name":"disabled-filter","width":390,"passed":true}
+{"name":"validation-register","width":390,"passed":true}
+{"name":"validation-onboarding","width":390,"passed":true}
+{"name":"projects","width":1440,"passed":true}
+{"name":"vacancies","width":1440,"passed":true}
+{"name":"programs","width":1440,"passed":true}
+{"name":"courses","width":1440,"passed":true}
+{"name":"profile","width":1440,"passed":true}
+{"name":"profile-edit","width":1440,"passed":true}
+{"name":"onboarding-0","width":1440,"passed":true}
+{"name":"onboarding-1","width":1440,"passed":true}
+{"name":"loading-page","width":1440,"passed":true}
+{"name":"loading-action","width":1440,"passed":true}
+{"name":"empty","width":1440,"passed":true}
+{"name":"error","width":1440,"passed":true}
+{"name":"disabled-action","width":1440,"passed":true}
+{"name":"disabled-filter","width":1440,"passed":true}
+{"name":"validation-register","width":1440,"passed":true}
+{"name":"validation-onboarding","width":1440,"passed":true}
+48 UI state checks passed
diff --git a/docs/mobile-polish/styles.log b/docs/mobile-polish/styles.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs/mobile-polish/tests.log b/docs/mobile-polish/tests.log
new file mode 100644
index 000000000..4b0aa0624
--- /dev/null
+++ b/docs/mobile-polish/tests.log
@@ -0,0 +1,1137 @@
+
+> procollab@0.0.0 test:ci
+> vitest run
+
+
+ RUN v3.2.6 Z:/Документы/PROCOLLAB-dev/procollab-dev-platform-responsive
+
+ ✓ projects/social_platform/src/app/api/chat/use-cases/edit-message.use-case.spec.ts (1 test) 39ms
+ ✓ projects/social_platform/src/app/ui/widgets/project-invite/profile-project-invite-modal.component.spec.ts (21 tests) 2998ms
+ ✓ Окно выбора проекта > локальный поиск нормализует пробелы и регистр, строка выбирается целиком и выделяется 649ms
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (base) > не закрашивает закладку при ошибке подписки
+[22:48:37.469] [ERROR] Error subscribing to project: {"kind":"add_project_subscription_error","cause":{}}
+
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (base) > сохраняет подписку и подтверждение при ошибке, после успешного повтора закрывает
+[22:48:37.609] [ERROR] Error unsubscribing from project: {"kind":"delete_project_subscription_error","cause":{}}
+
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (subs) > не закрашивает закладку при ошибке подписки
+[22:48:38.044] [ERROR] Error subscribing to project: {"kind":"add_project_subscription_error","cause":{}}
+
+stderr | projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts > InfoCard: асинхронная подписка (subs) > сохраняет подписку и подтверждение при ошибке, после успешного повтора закрывает
+[22:48:38.181] [ERROR] Error unsubscribing from project: {"kind":"delete_project_subscription_error","cause":{}}
+
+ ✓ projects/social_platform/src/app/ui/widgets/info-card/info-card-subscription.spec.ts (8 tests) 2570ms
+ ✓ InfoCard: асинхронная подписка (base) > закрашивает закладку после отложенного ответа без перезагрузки и второго клика 1430ms
+ ✓ projects/social_platform/src/app/ui/pages/members/members-mobile.spec.ts (7 tests) 2752ms
+ ✓ Мобильное представление участников > держит статистику перед мобильным списком, под desktop-фильтрами и не перезагружает её при поиске 1381ms
+ ✓ Мобильное представление участников > открывает ту же форму отдельно, сохраняет фильтры после закрытия, возвращает фокус 338ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/feed-news-preview/feed-news-preview.component.spec.ts (23 tests) 2856ms
+ ✓ FeedNewsPreviewComponent > project: нет пустой media-области; thumbnail появляется только с изображением 926ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.spec.ts (7 tests) 2897ms
+ ✓ Окно приглашения из редактора команды > CTA открывает окно с поиском, URL отсутствует, отправка неактивна до выбора и роли 1391ms
+ ✓ Окно приглашения из редактора команды > показывает public data, причины disabled, выбирает строку и очищает выбор 566ms
+ ✓ Окно приглашения из редактора команды > ошибка inline сохраняет выбор/роль, повтор защищён, успех закрывает и возвращает фокус 550ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/submit-task-answer.use-case.spec.ts (3 tests) 115ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.spec.ts (30 tests) 3809ms
+ ✓ AnalyticsDrilldownComponent: real overlay lifecycle > all: единое оформление списка и правильный заголовок 1066ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.spec.ts (12 tests) 4695ms
+ ✓ ProjectMainStepComponent > стандартная обложка предлагает загрузку и не выдаёт системный URL за загруженный файл 2189ms
+ ✓ ProjectMainStepComponent > пользовательская обложка предлагает только замену с клавиатуры, без кнопки сброса 354ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.spec.ts (6 tests) 5411ms
+ ✓ ProfileMainStepComponent user region > loads canonical city as selected user region without API side effects 3601ms
+ ✓ ProfileMainStepComponent user region > preserves untouched legacy city Набережные Челны through focus, blur and Escape 598ms
+ ✓ ProfileMainStepComponent user region > preserves untouched legacy city Мсква through focus, blur and Escape 423ms
+ ✓ projects/social_platform/src/app/ui/widgets/info-card/info-card.component.spec.ts (41 tests) 5868ms
+ ✓ InfoCardComponent: статусы моих проектов > 'draft' / 'Лидер': статус, доступ и единственный корректный маршрут 2351ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-attention.component.spec.ts (19 tests) 6205ms
+ ✓ Attention views: real overlay > participants: реальные поля, local date, legacy city, fallback, актуальный count 2464ms
+ ✓ Attention views: real overlay > server search только submit, clear, count и pagination из detail 586ms
+ ✓ Attention views: real overlay > not-submitted: server search via submit/button, clear and page 411ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-zero/stage-zero.component.spec.ts (3 tests) 1581ms
+ ✓ StageZeroComponent > should create 1013ms
+ ✓ StageZeroComponent > preserves an initial legacy city without automatically selecting a region 301ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/dashboard/dashboard.component.spec.ts (3 tests) 1402ms
+ ✓ ProjectsDashboard: контексты карточек > передаёт my/subs/base, ID и подписки; показывает нужный контекст каждого раздела 1210ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/projects-presentation.spec.ts (6 tests) 1258ms
+ ✓ ProjectsComponent: приглашение и активность на странице > сохраняет размещение активности в разделе dashboard 687ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/detail-cleanup.component.spec.ts (5 tests) 1583ms
+ ✓ Detail cleanup actions > renders create, open-existing and submitted CTA states without changing submitted disabling 887ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/edit/edit.component.spec.ts (3 tests) 1889ms
+ ✓ ProfileEditComponent > should create 1157ms
+ ✓ ProfileEditComponent > closes the skills library with the explicit close button 470ms
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps unrated CTA active and criteria editable when registration is past but evaluation is future
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > allows editing an existing rating until the evaluation deadline, then returns to readonly on success
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-case.component.spec.ts (12 tests) 2154ms
+ ✓ Case drilldown в существующем Overlay > selected: четыре колонки, реальные поля, null presentation и только один modal 1213ms
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > allows editing an existing rating until the evaluation deadline, then returns to readonly on success
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ ✓ projects/social_platform/src/app/ui/pages/projects/list/list.component.spec.ts (9 tests) 2461ms
+ ✓ ProjectsListComponent: контекст и track > /my: CTA выполняет один переход в detail 1130ms
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps expired CTA visible and all criteria readonly (rated=false)
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps expired CTA visible and all criteria readonly (rated=true)
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps CTA and criteria available for deadline
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > keeps CTA and criteria available for invalid deadline
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+stderr | projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts > RatingCardComponent > updates visible CTA and criteria on fresh closed/reopened program responses
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
+ when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
+ you. We recommend using this approach to avoid 'changed after checked' errors.
+
+ Example:
+ // Specify the `disabled` property at control creation time:
+ form = new FormGroup({
+ first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
+ last: new FormControl('Drew', Validators.required)
+ });
+
+ // Controls can also be enabled/disabled after creation:
+ form.get('first')?.enable();
+ form.get('last')?.disable();
+
+
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/rating-card.component.spec.ts (8 tests) 1624ms
+ ✓ RatingCardComponent > should create 459ms
+ ✓ RatingCardComponent > allows editing an existing rating until the evaluation deadline, then returns to readonly on success 332ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.spec.ts (8 tests) 1874ms
+ ✓ ProjectAdditionalStepComponent canonical form > required indicators follow backend metadata; optional text has no fake required error 884ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/edit.component.spec.ts (3 tests) 1370ms
+ ✓ ProjectEditComponent > should create 1155ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.spec.ts (11 tests) 1257ms
+ ✓ ProgramRoleWidgetComponent > shows skeleton without bogus zero counters 400ms
+ ✓ projects/social_platform/src/app/ui/widgets/info-card/info-card-list-contract.spec.ts (8 tests) 1030ms
+ ✓ Мои проекты: HTTP list → преобразование контракта → карточка > is_submitted=true, draft=false: lifecycle и доступ независимы 582ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/main.component.spec.ts (1 test) 847ms
+ ✓ MainComponent > should create 845ms
+ ✓ projects/social_platform/src/app/ui/primitives/input/input.component.spec.ts (20 tests) 931ms
+ ✓ InputComponent > should create the component 356ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/main/main.roles.spec.ts (4 tests) 1069ms
+ ✓ Program page: program-scoped news and role visibility > loads and shows both existing and newly created news for manager without member role 810ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-mid-side/profile-mid-side.component.spec.ts (4 tests) 995ms
+ ✓ ProfileMidSideComponent > показывает центрируемый empty state владельцу пустого профиля 667ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/list.component.spec.ts (2 tests) 1014ms
+ ✓ ProgramListComponent > should create 803ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.spec.ts (42 tests) 14302ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > не показывает общую выгрузку и не запрашивает проекты до открытия кейса 2473ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > клик строки 0 передаёт точный scope, включая нулевой кейс 448ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > клик строки 2 передаёт точный scope, включая нулевой кейс 397ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > клик строки 3 передаёт точный scope, включая нулевой кейс 408ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > keeps cases and evaluation as adjacent cards in the same two-column grid row 430ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > preserves backend counts/order/zero rows and appends withoutCase without mutations 342ms
+ ✓ ProgramAnalyticsComponent > cases from manager overview > renders controlled empty state when configured=true 319ms
+ ✓ ProgramAnalyticsComponent > Участники без команды: button, zero disabled, tooltip отдельно 302ms
+ ✓ ProgramAnalyticsComponent > Работы ожидают оценивания: button, zero disabled, tooltip отдельно 405ms
+ ✓ ProgramAnalyticsComponent > not-submitted: порядок, активная/нулевая строка и tooltip отдельно 390ms
+ ✓ ProgramAnalyticsComponent > non-competitive скрывает строку даже с notSubmitted > 0 и не делает detail request 363ms
+ ✓ ProgramAnalyticsComponent > строит воронки только из participantFunnel и solutionFunnel 406ms
+ ✓ ProgramAnalyticsComponent > в open mode показывает статусы проектов без partial и трактует max как лимит 368ms
+ ✓ ProgramAnalyticsComponent > использует attention backend напрямую, без frontend approximation 312ms
+ ✓ ProgramAnalyticsComponent > marks zero attention rows and keeps tooltip controls separate and keyboard accessible 368ms
+ ✓ ProgramAnalyticsComponent > exports each loaded region dataset independently and prevents repeated clicks 320ms
+ ✓ projects/social_platform/src/app/ui/pages/feed/feed.component.spec.ts (1 test) 937ms
+ ✓ FeedComponent: порядок и представление карточек #372 > сохраняет шесть начальных карточек, ключи type:id и append в DOM без перестановки 935ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-form/news-form.component.spec.ts (7 tests) 832ms
+ ✓ NewsFormComponent > should create 367ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/info.component.spec.ts (3 tests) 892ms
+ ✓ VacancyInfoComponent PROCOLLAB CV > разрешает прикрепить PROCOLLAB CV при пустом accompanyingFile 654ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/news-card.component.spec.ts (5 tests) 1060ms
+ ✓ NewsCardComponent > should create 684ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/info.component.spec.ts (1 test) 748ms
+ ✓ ProjectInfoComponent > should create 746ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-mid-side/projects-mid-side.component.spec.ts (4 tests) 706ms
+ ✓ ProjectsMidSideComponent > shows the complete project description after expansion 693ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-attention-route.spec.ts (3 tests) 946ms
+ ✓ Attention SPA: observable route → resolver → overview > participants-without-team отменяется до Program(13), без нового auto request 698ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/register/register.component.spec.ts (4 tests) 915ms
+ ✓ RegisterComponent > should create 635ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.spec.ts (12 tests) 730ms
+ ✓ VacancyResponsesComponent > показывает два действия только для pending response 452ms
+ ✓ projects/social_platform/src/app/ui/widgets/project-vacancy-card/project-vacancy-card.component.spec.ts (10 tests) 580ms
+ ✓ ProjectVacancyCardComponent > should create 313ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/main/main.component.spec.ts (2 tests) 648ms
+ ✓ MainComponent > should create 586ms
+stdout | projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts > ProgramRegisterComponent > onSubmit > вызывает use-case с programId и значениями формы
+[22:48:53.656] [DEBUG] Route changed from ProgramRegisterComponent
+
+stdout | projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts > ProgramRegisterComponent > onSubmit > навигирует на детальную страницу программы при успехе use-case
+[22:48:53.695] [DEBUG] Route changed from ProgramRegisterComponent
+
+stdout | projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts > ProgramRegisterComponent > onSubmit > срабатывает по клику на кнопку submit в DOM
+[22:48:53.777] [DEBUG] Route changed from ProgramRegisterComponent
+
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/register/register.component.spec.ts (7 tests) 698ms
+ ✓ ProgramRegisterComponent > ngOnInit строит форму из schema резолвера > создаёт FormGroup с полем под каждый ключ schema 434ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/profile-news/profile-news.component.spec.ts (1 test) 525ms
+ ✓ ProfileNewsComponent > should create 524ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/login/login.component.spec.ts (4 tests) 668ms
+ ✓ LoginComponent > should create 475ms
+ ✓ projects/social_platform/src/app/ui/widgets/region-select/region-select.component.spec.ts (12 tests) 591ms
+ ✓ projects/social_platform/src/app/ui/pages/members/members.component.spec.ts (1 test) 577ms
+ ✓ MembersComponent > should create 575ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-two/stage-two.component.spec.ts (4 tests) 733ms
+ ✓ StageTwoComponent > should create 486ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/vacancies.component.spec.ts (2 tests) 557ms
+ ✓ VacanciesComponent > should create 465ms
+ ✓ projects/social_platform/src/app/ui/pages/office/office.component.spec.ts (3 tests) 716ms
+ ✓ OfficeComponent > should create 599ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/list/list.component.spec.ts (7 tests) 548ms
+ ✓ VacanciesListComponent > должен вызвать vacancyInfoService.init() при инициализации компонента 343ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.spec.ts (6 tests) 409ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-form.service.spec.ts (8 tests) 473ms
+stderr | projects/social_platform/src/app/ui/pages/auth/set-password/set-password.component.spec.ts > SetPasswordComponent > should create
+[22:48:56.392] [ERROR] Token is missing
+
+ ✓ projects/social_platform/src/app/ui/pages/auth/set-password/set-password.component.spec.ts (1 test) 457ms
+ ✓ SetPasswordComponent > should create 456ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat-direct/chat-direct.component.spec.ts (1 test) 480ms
+ ✓ ChatDirectComponent > should create 471ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.component.spec.ts (1 test) 444ms
+ ✓ NewsDetailComponent > should create 439ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/feed-news-modal/feed-news-modal.component.spec.ts (1 test) 446ms
+ ✓ FeedNewsModalComponent > показывает полный текст, переносы, ссылку, все файлы и contain-карусель без detail HTTP 444ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/reset-password/reset-password.component.spec.ts (1 test) 352ms
+ ✓ ResetPasswordComponent > should create 350ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/detail/info/course-module-card/course-module-card.component.spec.ts (7 tests) 448ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-one/stage-one.component.spec.ts (1 test) 386ms
+ ✓ StageOneComponent > should create 384ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.spec.ts (9 tests) 421ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/program-projects-filter/program-projects-filter.component.spec.ts (2 tests) 430ms
+ ✓ ProjectsFilterComponent > should create 334ms
+ ✓ projects/social_platform/src/app/ui/primitives/select/select.component.spec.ts (7 tests) 438ms
+ ✓ projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.spec.ts (2 tests) 393ms
+ ✓ ProfileRightSideComponent > keeps the complete long project title in the profile project list DOM 333ms
+ ✓ projects/social_platform/src/app/ui/primitives/textarea/textarea.component.spec.ts (6 tests) 390ms
+ ✓ projects/social_platform/src/app/ui/pages/members/member-card/member-card.component.spec.ts (7 tests) 445ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/invite-card/invite-card.component.spec.ts (4 tests) 436ms
+ ✓ InviteCardComponent > should create 341ms
+ ✓ projects/social_platform/src/app/ui/widgets/chat-window/chat-window.component.spec.ts (1 test) 470ms
+ ✓ ChatWindowComponent > should create 467ms
+ ✓ projects/social_platform/src/app/ui/primitives/avatar-control/avatar-control.component.spec.ts (1 test) 410ms
+ ✓ AvatarControlComponent > should create 407ms
+ ✓ projects/social_platform/src/app/ui/pages/program/main/main.component.spec.ts (1 test) 378ms
+ ✓ MainComponent > should create 376ms
+stdout | projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.spec.ts > ProjectsFilterComponent > сохраняет справочник отраслей и фильтрацию через query-параметр industry
+[22:48:59.612] [DEBUG] Query change from ProjectsComponent
+
+ ✓ projects/social_platform/src/app/ui/widgets/projects-filter/projects-filter.component.spec.ts (2 tests) 418ms
+ ✓ ProjectsFilterComponent > should create 366ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.spec.ts (2 tests) 383ms
+ ✓ projects/social_platform/src/app/ui/pages/members/member-statistics-card/member-statistics-card.component.spec.ts (11 tests) 359ms
+ ✓ projects/social_platform/src/app/ui/primitives/modal/modal.component.spec.ts (4 tests) 363ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/chat/chat.component.spec.ts (1 test) 417ms
+ ✓ ChatComponent > should create 416ms
+ ✓ projects/social_platform/src/app/ui/widgets/vacancy-card/vacancy-card.component.spec.ts (5 tests) 558ms
+ ✓ VacancyCardComponent > should create 418ms
+ ✓ projects/social_platform/src/app/ui/primitives/tooltip/tooltip.component.spec.ts (4 tests) 543ms
+ ✓ TooltipComponent overlay mode > should use overlay mode for analytics tooltip 393ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/project-activity-card/project-activity-card.component.spec.ts (11 tests) 411ms
+ ✓ projects/social_platform/src/app/utils/export-regions-workbook.spec.ts (1 test) 372ms
+ ✓ region XLSX workbook integration > generates a ZIP/OOXML workbook with real string and number cells 370ms
+ ✓ projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.spec.ts (15 tests) 421ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/invite/invite.repository.spec.ts (9 tests) 97ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat.component.spec.ts (1 test) 347ms
+ ✓ ChatComponent > should create 344ms
+ ✓ projects/social_platform/src/app/ui/pages/members/members-filters/members-filters.component.spec.ts (2 tests) 357ms
+ ✓ MembersFiltersComponent > should create 311ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/video-task/info-task.component.spec.ts (1 test) 284ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.spec.ts (1 test) 292ms
+ ✓ projects/social_platform/src/app/ui/widgets/vacancy-filter/vacancy-filter.component.spec.ts (1 test) 267ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/program-case-projects.use-case.spec.ts (15 tests) 115ms
+ ✓ projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.spec.ts (1 test) 326ms
+ ✓ OpenVacancyComponent > показывает тип, дату, источник, роль, описание, навыки и CTA 321ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.spec.ts (6 tests) 300ms
+ ✓ projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.spec.ts (3 tests) 317ms
+ ✓ projects/social_platform/src/app/ui/widgets/skills-group/skills-group.component.spec.ts (4 tests) 295ms
+ ✓ projects/social_platform/src/app/ui/widgets/message-input/message-input.component.spec.ts (1 test) 423ms
+ ✓ MessageInputComponent > should create 420ms
+ ✓ projects/social_platform/src/app/ui/widgets/project-invite/project-invite-role-input.component.spec.ts (4 tests) 336ms
+ ✓ projects/social_platform/src/app/ui/widgets/specializations-group/specializations-group.component.spec.ts (4 tests) 456ms
+ ✓ SpecializationsGroupComponent > should create 311ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.spec.ts (1 test) 233ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/collaborator-card/collaborator-card.component.spec.ts (2 tests) 269ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-three/stage-three.component.spec.ts (1 test) 254ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/projects-edit-info.service.spec.ts (22 tests) 288ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-cover-reset.service.spec.ts (11 tests) 309ms
+ ✓ projects/social_platform/src/app/ui/pages/office/delete-confirm/delete-confirm.component.spec.ts (1 test) 302ms
+ ✓ projects/social_platform/src/app/app.component.spec.ts (1 test) 274ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-analytics-info.service.spec.ts (15 tests) 149ms
+ ✓ projects/social_platform/src/app/ui/widgets/header/header.component.spec.ts (1 test) 252ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-left-side/projects-left-side.component.spec.ts (4 tests) 285ms
+ ✓ projects/social_platform/src/app/ui/widgets/vacancy-skills/vacancy-skills.component.spec.ts (2 tests) 272ms
+ ✓ projects/social_platform/src/app/ui/widgets/chat-window/chat-message/chat-message.component.spec.ts (1 test) 298ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-resource.use-case.spec.ts (3 tests) 52ms
+ ✓ projects/ui/src/lib/components/layout/invite-manage-card/invite-manage-card.component.spec.ts (1 test) 237ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/onboarding.component.spec.ts (1 test) 213ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-additional.service.spec.ts (39 tests) 279ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/complete/complete.component.spec.ts (5 tests) 260ms
+ ✓ projects/social_platform/src/app/api/member/facades/members-info.service.spec.ts (16 tests) 189ms
+ ✓ projects/ui/src/lib/components/layout/profile-info/profile-info.component.spec.ts (1 test) 221ms
+ ✓ projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.spec.ts (5 tests) 283ms
+ ✓ projects/social_platform/src/app/api/vacancy/facades/vacancy-detail-info.service.spec.ts (17 tests) 170ms
+ ✓ projects/ui/src/lib/components/primitives/avatar/avatar.component.spec.ts (6 tests) 223ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.spec.ts (5 tests) 199ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-form.service.spec.ts (13 tests) 221ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.spec.ts (1 test) 230ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-analytics-attention.service.spec.ts (42 tests) 262ms
+ ✓ projects/social_platform/src/app/ui/widgets/cookie-consent/cookie-consent.component.spec.ts (5 tests) 240ms
+stdout | projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.spec.ts > FeedComponent > показывает счётчики всех шести категорий независимо от фильтра
+[22:49:08.788] [DEBUG] Query change from FeedFilterComponent
+
+ ✓ projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.spec.ts (2 tests) 281ms
+ ✓ projects/social_platform/src/app/ui/pages/error/error.component.spec.ts (1 test) 142ms
+ ✓ projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-left-side/vacancies-left-side.component.spec.ts (1 test) 216ms
+ ✓ projects/social_platform/src/app/ui/primitives/avatar/avatar.component.spec.ts (6 tests) 244ms
+ ✓ projects/social_platform/src/app/ui/widgets/skills-basket/skills-basket.component.spec.ts (4 tests) 260ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/list/course/course.component.spec.ts (1 test) 282ms
+ ✓ projects/social_platform/src/app/ui/pages/onboarding/stage-three/user-type-card/user-type-card.component.spec.ts (1 test) 148ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-news.repository.spec.ts (8 tests) 90ms
+ ✓ projects/ui/src/lib/components/primitives/button/button-states.spec.ts (2 tests) 204ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-subscription.repository.spec.ts (4 tests) 78ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-role-widget.service.spec.ts (11 tests) 139ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.spec.ts (1 test) 218ms
+ ✓ projects/social_platform/src/app/ui/primitives/button/button.component.spec.ts (6 tests) 247ms
+ ✓ projects/social_platform/src/app/ui/widgets/news-card/carousel/carousel.component.spec.ts (2 tests) 207ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-form-autosave.service.spec.ts (24 tests) 218ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-team.service.spec.ts (19 tests) 156ms
+ ✓ projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.spec.ts (1 test) 211ms
+ ✓ projects/social_platform/src/app/ui/primitives/bar/bar.component.spec.ts (1 test) 199ms
+ ✓ projects/ui/src/lib/components/primitives/icon/icon.component.spec.ts (5 tests) 194ms
+ ✓ projects/social_platform/src/app/ui/primitives/loader/loader.component.spec.ts (4 tests) 179ms
+ ✓ projects/social_platform/src/app/ui/primitives/file-upload-item/file-upload-item.component.spec.ts (1 test) 211ms
+ ✓ projects/social_platform/src/app/ui/primitives/search/search.component.spec.ts (2 tests) 227ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/program/program.repository.spec.ts (30 tests) 188ms
+ ✓ projects/social_platform/src/app/ui/pages/error/not-found/error-not-found.component.spec.ts (1 test) 145ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.spec.ts (1 test) 223ms
+ ✓ projects/social_platform/src/app/ui/pages/feed/new-project/new-project.component.spec.ts (1 test) 238ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-vacancy.service.spec.ts (13 tests) 196ms
+ ✓ projects/ui/src/lib/components/layout/sidebar/sidebar.component.spec.ts (1 test) 193ms
+ ✓ projects/social_platform/src/app/api/feed/facades/feed-info.service.spec.ts (3 tests) 67ms
+ ✓ projects/social_platform/src/app/ui/primitives/icon/icon.component.spec.ts (5 tests) 195ms
+ ✓ projects/social_platform/src/app/ui/primitives/tag/tag.component.spec.ts (1 test) 180ms
+ ✓ projects/social_platform/src/app/api/feed/use-cases/toggle-feed-like.use-case.spec.ts (4 tests) 63ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-goal.use-case.spec.ts (3 tests) 79ms
+ ✓ projects/ui/src/lib/components/primitives/back/back.component.spec.ts (1 test) 292ms
+ ✓ projects/social_platform/src/app/ui/primitives/img-card/img-card.component.spec.ts (1 test) 205ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-partner.use-case.spec.ts (3 tests) 62ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-all-projects.use-case.spec.ts (3 tests) 83ms
+ ✓ projects/social_platform/src/app/ui/primitives/switch/switch.component.spec.ts (4 tests) 324ms
+ ✓ projects/social_platform/src/app/domain/shared/chat-state.service.spec.ts (1 test) 56ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project.repository.spec.ts (21 tests) 189ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-project-subscription.use-case.spec.ts (3 tests) 90ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-all-members.use-case.spec.ts (3 tests) 65ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/add-project-news.use-case.spec.ts (3 tests) 78ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/confirm-password-reset/confirm-password-reset.component.spec.ts (1 test) 196ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-all-projects.use-case.spec.ts (3 tests) 66ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-analytics-drilldown.service.spec.ts (10 tests) 153ms
+ ✓ projects/social_platform/src/app/ui/pages/courses/detail/info/course-module-card/circle-progress-bar/circle-progress-bar.component.spec.ts (1 test) 322ms
+ ✓ CircleProgressBarComponent > should create 319ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/get-profile-news-detail.use-case.spec.ts (3 tests) 87ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/vacancy/vacancy-http.adapter.spec.ts (5 tests) 79ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-cover-contract.spec.ts (3 tests) 79ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/send-vacancy-response.use-case.spec.ts (4 tests) 77ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-case-projects.service.spec.ts (11 tests) 150ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/confirm-email/confirm-email.component.spec.ts (1 test) 162ms
+ ✓ projects/social_platform/src/app/ui/primitives/file-item/file-item.component.spec.ts (1 test) 284ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-manager-attention.use-case.spec.ts (23 tests) 163ms
+ ✓ projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.spec.ts (1 test) 296ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/assign-project-program.spec.ts (3 tests) 55ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-resource.repository.spec.ts (4 tests) 68ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/services/program/detail-program-info.service.spec.ts (15 tests) 154ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/auth/auth-http.adapter.spec.ts (24 tests) 222ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/services/profile/detail-profile-invite.spec.ts (9 tests) 210ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program.use-case.spec.ts (3 tests) 117ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/load-project-files.use-case.spec.ts (3 tests) 111ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/program-link-fields.use-cases.spec.ts (15 tests) 178ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/ui/project-vacancy-ui.service.spec.ts (17 tests) 314ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/detail.resolver.spec.ts (10 tests) 124ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/add-profile-news.use-case.spec.ts (3 tests) 68ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/read-news.use-case.spec.ts (3 tests) 68ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/register.use-case.spec.ts (5 tests) 82ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/vacancy/vacancy.repository.spec.ts (16 tests) 207ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-subscribers.use-case.spec.ts (3 tests) 57ms
+ ✓ projects/social_platform/src/app/api/program/program-widget-presentation.spec.ts (30 tests) 78ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/toggle-project-news-like.use-case.spec.ts (3 tests) 86ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-collaborators-http.adapter.spec.ts (3 tests) 69ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/auth/auth.repository.spec.ts (17 tests) 357ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/feed/feed-http.adapter.spec.ts (1 test) 48ms
+ ✓ projects/social_platform/src/app/ui/pages/error/error-code/error-code.component.spec.ts (1 test) 191ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/program/program-http.adapter.spec.ts (22 tests) 174ms
+ ✓ projects/social_platform/src/app/api/onboarding/facades/stages/onboarding-stage-zero-info.service.spec.ts (7 tests) 160ms
+ ✓ projects/social_platform/src/app/ui/pages/auth/auth.component.spec.ts (1 test) 179ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/add-project-subscription.use-case.spec.ts (3 tests) 82ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/toggle-profile-news-like.use-case.spec.ts (3 tests) 68ms
+ ✓ projects/social_platform/src/app/api/member/facades/member-statistics.facade.spec.ts (5 tests) 99ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-news-detail.use-case.spec.ts (3 tests) 80ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat.resolver.spec.ts (1 test) 49ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/reset-password.use-case.spec.ts (3 tests) 70ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/get-my-invites.use-case.spec.ts (3 tests) 69ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/update-form.use-case.spec.ts (3 tests) 70ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-edit-info.service.spec.ts (4 tests) 150ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-news-http.adapter.spec.ts (7 tests) 110ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-collaborators.repository.spec.ts (3 tests) 72ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/fetch-project-news.use-case.spec.ts (3 tests) 58ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-programs.use-case.spec.ts (3 tests) 78ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-project.use-case.spec.ts (3 tests) 97ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/delete-news.use-case.spec.ts (3 tests) 72ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/reset-project-cover.use-case.spec.ts (13 tests) 127ms
+ ✓ projects/core/src/lib/interceptors/bearer-token.interceptor.spec.ts (1 test) 72ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/accept-response.use-case.spec.ts (3 tests) 71ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/program-projects-filter/service/program-projects-filter-info.service.spec.ts (1 test) 71ms
+ ✓ projects/social_platform/src/app/api/feed/use-cases/read-feed-news.use-case.spec.ts (4 tests) 76ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-contacts.service.spec.ts (3 tests) 74ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/chat/chat-ws.adapter.spec.ts (14 tests) 121ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project.use-case.spec.ts (3 tests) 51ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/delete-message.use-case.spec.ts (1 test) 45ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/submit-competitive-project.use-case.spec.ts (3 tests) 67ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-program.repository.spec.ts (5 tests) 91ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-goals-http.adapter.spec.ts (4 tests) 69ms
+ ✓ projects/social_platform/src/app/api/member/use-cases/get-members.use-case.spec.ts (4 tests) 84ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/list/all.resolver.spec.ts (1 test) 55ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/download-cv.use-case.spec.ts (3 tests) 60ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-http.adapter.spec.ts (8 tests) 107ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/edit-profile-news.use-case.spec.ts (3 tests) 67ms
+ ✓ projects/social_platform/src/app/api/courses/facades/ui/course-detail-ui-info.service.spec.ts (5 tests) 65ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-project-ratings.use-case.spec.ts (3 tests) 55ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/services/rating-card.service.spec.ts (9 tests) 169ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/profile/profile-news-http.adapter.spec.ts (7 tests) 95ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/member/member-statistics-contract.spec.ts (6 tests) 160ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-partners.use-case.spec.ts (3 tests) 84ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-vacancies.use-case.spec.ts (3 tests) 66ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/login.use-case.spec.ts (4 tests) 92ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-goals.use-case.spec.ts (3 tests) 91ms
+ ✓ projects/core/src/lib/interceptors/camelcase.interceptor.spec.ts (6 tests) 166ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-data-schema.use-case.spec.ts (3 tests) 101ms
+ ✓ projects/social_platform/src/app/api/project/facades/projects-info.service.spec.ts (3 tests) 69ms
+ ✓ projects/social_platform/src/app/api/vacancy/facades/vacancy-info.service.spec.ts (4 tests) 94ms
+ ✓ projects/social_platform/src/app/api/kanban/use-cases/get-task.use-case.spec.ts (4 tests) 82ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/update-goal.use-case.spec.ts (3 tests) 110ms
+ ✓ projects/social_platform/src/app/api/program/program-widget-refresh.spec.ts (8 tests) 99ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-goals.repository.spec.ts (4 tests) 102ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/fetch-profile-news.use-case.spec.ts (3 tests) 74ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/projects.resolver.spec.ts (2 tests) 61ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/delete-profile-news.use-case.spec.ts (3 tests) 67ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/chat/chat-realtime.repository.spec.ts (3 tests) 75ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-messages.use-case.spec.ts (2 tests) 66ms
+ ✓ projects/core/src/lib/services/file/file.service.spec.ts (1 test) 52ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-count-contract.spec.ts (1 test) 77ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/industry/industry.repository.spec.ts (3 tests) 79ms
+ ✓ projects/social_platform/src/app/api/kanban/use-cases/get-column-tasks.use-case.spec.ts (3 tests) 100ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/courses/courses-http.adapter.spec.ts (5 tests) 90ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-partner-http.adapter.spec.ts (4 tests) 88ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/resend-email.use-case.spec.ts (3 tests) 83ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/profile/profile-news.repository.spec.ts (8 tests) 217ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/program/program-news-http.adapter.spec.ts (6 tests) 123ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/send-for-user.use-case.spec.ts (3 tests) 162ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/chat/chat-http.adapter.spec.ts (4 tests) 140ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/specializations/specializations-http.adapter.spec.ts (2 tests) 166ms
+ ✓ projects/social_platform/src/app/api/searches/searches.service.spec.ts (5 tests) 147ms
+ ✓ projects/social_platform/src/app/api/skills/use-cases/get-skills-nested.use-case.spec.ts (3 tests) 58ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/post-vacancy.use-case.spec.ts (3 tests) 87ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-my-vacancies.use-case.spec.ts (3 tests) 91ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/read-profile-news.use-case.spec.ts (3 tests) 86ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-course-structure.use-case.spec.ts (3 tests) 108ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-rating.repository.spec.ts (6 tests) 183ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/delete-vacancy.use-case.spec.ts (3 tests) 113ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/rate-project.use-case.spec.ts (3 tests) 229ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/register-program.use-case.spec.ts (3 tests) 215ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/apply-project-to-program.use-case.spec.ts (3 tests) 179ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-program-http.adapter.spec.ts (3 tests) 283ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-resources.use-case.spec.ts (3 tests) 119ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-role-widget.use-case.spec.ts (7 tests) 164ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/load-messages.use-case.spec.ts (3 tests) 128ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/list/my.resolver.spec.ts (1 test) 57ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/program-detail-main-info.service.spec.ts (3 tests) 235ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/member/member.repository.spec.ts (1 test) 95ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-manager-overview.use-case.spec.ts (2 tests) 119ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/transfer-project-ownership.use-case.spec.ts (3 tests) 102ms
+ ✓ projects/core/src/lib/guards/auth/auth-required.guard.spec.ts (1 test) 157ms
+ ✓ projects/social_platform/src/app/api/invite/facades/invite-participant-search.facade.spec.ts (4 tests) 219ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/chat/chat.resolver.spec.ts (1 test) 119ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-course-detail.use-case.spec.ts (3 tests) 330ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/check-unreads.use-case.spec.ts (3 tests) 134ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/connect-chat.use-case.spec.ts (1 test) 62ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/accept-invite.use-case.spec.ts (3 tests) 78ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/get-project-invites.use-case.spec.ts (3 tests) 148ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/invite/invite-http.adapter.spec.ts (7 tests) 180ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-project-responses.use-case.spec.ts (3 tests) 160ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-set-online.use-case.spec.ts (2 tests) 111ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.resolver.spec.ts (1 test) 105ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/toggle-like.use-case.spec.ts (3 tests) 128ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-my-projects.use-case.spec.ts (3 tests) 278ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-partner.use-case.spec.ts (3 tests) 148ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/program/program-news.repository.spec.ts (6 tests) 247ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-goals.use-case.spec.ts (3 tests) 98ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/chat/chat.repository.spec.ts (3 tests) 171ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/program/program-case-http.integration.spec.ts (2 tests) 170ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/ui/project-team-ui.service.spec.ts (2 tests) 123ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/industry/industry-http.adapter.spec.ts (1 test) 100ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/edit-news.use-case.spec.ts (3 tests) 168ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/project/project-partner.repository.spec.ts (4 tests) 185ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/courses/courses.repository.spec.ts (5 tests) 237ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/update-vacancy.use-case.spec.ts (3 tests) 335ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-manager-assignments.use-case.spec.ts (6 tests) 247ms
+ ✓ projects/core/src/lib/services/validation/validation.service.spec.ts (1 test) 160ms
+ ✓ projects/core/src/lib/services/api/api.service.spec.ts (1 test) 76ms
+ ✓ projects/social_platform/src/app/ui/pages/program/detail/register/register.resolver.spec.ts (1 test) 65ms
+ ✓ projects/core/src/lib/services/tokens/token.service.spec.ts (1 test) 139ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-resource-http.adapter.spec.ts (4 tests) 163ms
+ ✓ projects/social_platform/src/app/api/kanban/use-cases/get-board.use-case.spec.ts (4 tests) 271ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-project-news.use-case.spec.ts (3 tests) 94ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/reject-response.use-case.spec.ts (3 tests) 77ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/add-news.use-case.spec.ts (3 tests) 85ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-vacancy-detail.use-case.spec.ts (3 tests) 90ms
+ ✓ projects/social_platform/src/app/api/skills/use-cases/search-skills.use-case.spec.ts (3 tests) 94ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/start-typing.use-case.spec.ts (1 test) 124ms
+ ✓ projects/core/src/lib/services/websockets/websocket.service.spec.ts (1 test) 140ms
+ ✓ projects/core/src/lib/services/error/error.service.spec.ts (1 test) 135ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/participating-program.use-case.spec.ts (3 tests) 104ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-edit-message.use-case.spec.ts (2 tests) 70ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/delete-project.use-case.spec.ts (3 tests) 148ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/member/member-http.adapter.spec.ts (2 tests) 85ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/update-resource.use-case.spec.ts (3 tests) 105ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat-groups.resolver.spec.ts (1 test) 46ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-course-lesson.use-case.spec.ts (3 tests) 112ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/create-resource.use-case.spec.ts (3 tests) 164ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/subscription/subscription-http.adapter.spec.ts (4 tests) 140ms
+ ✓ projects/core/src/lib/services/error/global-error-handler.service.spec.ts (1 test) 151ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/reject-invite.use-case.spec.ts (3 tests) 103ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/read-message.use-case.spec.ts (1 test) 120ms
+ ✓ projects/social_platform/src/app/api/profile/use-cases/save-profile.use-case.spec.ts (3 tests) 162ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/remove-project-collaborator.use-case.spec.ts (3 tests) 158ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/get-program-filters.use-case.spec.ts (3 tests) 170ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/project/project-rating-http.adapter.spec.ts (4 tests) 168ms
+ ✓ projects/social_platform/src/app/api/onboarding/facades/stages/ui/onboarding-stage-one-ui-info.service.spec.ts (1 test) 149ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/feed/feed.repository.spec.ts (1 test) 83ms
+ ✓ projects/social_platform/src/app/domain/shared/entity-cache.spec.ts (11 tests) 89ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-set-offline.use-case.spec.ts (2 tests) 165ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-typing.use-case.spec.ts (2 tests) 88ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/get-project-subscriptions.use-case.spec.ts (3 tests) 200ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/revoke-invite.use-case.spec.ts (3 tests) 195ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/edit-project-news.use-case.spec.ts (3 tests) 175ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/set-password.use-case.spec.ts (3 tests) 177ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-delete-message.use-case.spec.ts (2 tests) 92ms
+ ✓ projects/social_platform/src/app/api/onboarding/onboarding.service.spec.ts (1 test) 106ms
+ ✓ projects/social_platform/src/app/api/auth/auth.service.spec.ts (1 test) 131ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/specializations/specializations.repository.spec.ts (2 tests) 100ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/read-project-news.use-case.spec.ts (3 tests) 121ms
+ ✓ projects/social_platform/src/app/api/project/use-cases/leave-project.use-case.spec.ts (3 tests) 100ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/create-program-filters.use-case.spec.ts (3 tests) 80ms
+ ✓ projects/social_platform/src/app/api/project/facades/edit/project-form.factory.spec.ts (4 tests) 55ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/observe-read-message.use-case.spec.ts (2 tests) 75ms
+ ✓ projects/social_platform/src/app/api/auth/use-cases/update-profile.use-case.spec.ts (3 tests) 138ms
+ ✓ projects/social_platform/src/app/infrastructure/repository/skills/skills.repository.spec.ts (2 tests) 137ms
+ ✓ projects/social_platform/src/app/api/invite/use-cases/update-invite.use-case.spec.ts (3 tests) 142ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/fetch-news.use-case.spec.ts (3 tests) 139ms
+ ✓ projects/social_platform/src/app/api/vacancy/use-cases/get-vacancy-responses.use-case.spec.ts (2 tests) 97ms
+ ✓ projects/social_platform/src/app/api/courses/use-cases/get-courses.use-case.spec.ts (3 tests) 164ms
+ ✓ projects/social_platform/src/app/api/chat/use-cases/send-message.use-case.spec.ts (1 test) 111ms
+ ✓ projects/social_platform/src/app/ui/pages/chat/chat-direct/chat-direct.resolver.spec.ts (1 test) 87ms
+ ✓ projects/social_platform/src/app/api/feed/facades/ui/feed-ui-info.service.spec.ts (1 test) 33ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/skills/skills-http.adapter.spec.ts (2 tests) 127ms
+ ✓ projects/social_platform/src/app/api/feed/use-cases/fetch-feed.use-case.spec.ts (3 tests) 125ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/detail/info/info.resolver.spec.ts (1 test) 75ms
+ ✓ projects/social_platform/src/app/api/program/use-cases/filter-project-ratings.use-case.spec.ts (3 tests) 340ms
+ ✓ projects/social_platform/src/app/ui/primitives/modal/modal.service.spec.ts (1 test) 79ms
+ ✓ projects/social_platform/src/app/ui/widgets/detail/services/detail-info.service.spec.ts (1 test) 115ms
+ ✓ projects/social_platform/src/app/ui/pages/office/snackbar/animation/animation.service.spec.ts (1 test) 101ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/edit/edit.resolver.spec.ts (1 test) 121ms
+ ✓ projects/social_platform/src/app/api/program/facades/detail/ui/program-detail-main-ui-info.service.spec.ts (13 tests) 79ms
+ ✓ projects/social_platform/src/app/ui/services/notification/notification.service.spec.ts (1 test) 89ms
+ ✓ projects/social_platform/src/app/utils/export-regions.spec.ts (3 tests) 28ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-save-error.utils.spec.ts (5 tests) 34ms
+ ✓ projects/core/src/consts/lists/russian-regions-list.const.spec.ts (7 tests) 100ms
+ ✓ projects/core/src/lib/pipes/formatters/parse-breaks.pipe.spec.ts (1 test) 11ms
+ ✓ projects/social_platform/src/app/api/profile/facades/edit/profile-edit-validation.utils.spec.ts (9 tests) 125ms
+ ✓ projects/social_platform/src/app/utils/program-case-analytics.spec.ts (14 tests) 50ms
+ ✓ projects/social_platform/src/app/api/vacancy/vacancy-response-error.spec.ts (8 tests) 16ms
+ ✓ projects/social_platform/src/app/api/project/facades/detail/ui/projects-detail-ui.service.spec.ts (1 test) 11ms
+ ✓ projects/core/src/lib/pipes/controls/form-control.pipe.spec.ts (1 test) 7ms
+ ✓ projects/social_platform/src/app/infrastructure/adapters/courses/local-storage-seen-modules.adapter.spec.ts (4 tests) 10ms
+ ✓ projects/social_platform/src/app/api/invite/mappers/map-invite-send-error.spec.ts (24 tests) 30ms
+ ✓ projects/core/src/lib/pipes/user/user-role.pipe.spec.ts (1 test) 21ms
+ ✓ projects/social_platform/src/app/utils/program-analytics-assignment.spec.ts (9 tests) 29ms
+ ✓ projects/social_platform/src/app/ui/pages/projects/projects-activity-placement.spec.ts (4 tests) 50ms
+ ✓ projects/social_platform/src/app/domain/invite/invite-candidates.spec.ts (2 tests) 27ms
+ ✓ projects/social_platform/src/app/api/member/member-filters.spec.ts (10 tests) 17ms
+ ✓ projects/core/src/lib/pipes/user/user-links.pipe.spec.ts (1 test) 10ms
+ ✓ projects/social_platform/src/app/api/profile/facades/detail/ui/profile-detail-ui-info.service.spec.ts (4 tests) 21ms
+ ✓ projects/core/src/lib/pipes/formatters/parse-links.pipe.spec.ts (1 test) 12ms
+ ✓ projects/core/src/lib/pipes/transformers/salary-trasform.pipe.spec.ts (1 test) 12ms
+ ✓ projects/core/src/lib/pipes/formatters/years-from-birthday.pipe.spec.ts (1 test) 9ms
+ ✓ projects/core/src/lib/pipes/formatters/pluralize.pipe.spec.ts (1 test) 7ms
+ ✓ projects/core/src/lib/pipes/formatters/dayjs.pipe.spec.ts (1 test) 4ms
+ ✓ projects/core/src/lib/pipes/transformers/link-transform.pipe.spec.ts (1 test) 4ms
+ ✓ projects/social_platform/src/app/ui/pipes/file-type.pipe.spec.ts (1 test) 4ms
+ ✓ projects/core/src/lib/pipes/controls/control-error.pipe.spec.ts (1 test) 5ms
+ ✓ projects/social_platform/src/app/ui/routes/program/detail.routes.spec.ts (2 tests) 6ms
+
+ Test Files 406 passed (406)
+ Tests 2006 passed (2006)
+ Start at 22:48:06
+ Duration 116.49s (transform 45.72s, setup 634.27s, collect 326.70s, tests 151.59s, environment 41.13s, prepare 131.22s)
+
diff --git a/docs/mobile-polish/ui-tests.log b/docs/mobile-polish/ui-tests.log
new file mode 100644
index 000000000..13434a99b
--- /dev/null
+++ b/docs/mobile-polish/ui-tests.log
@@ -0,0 +1,15 @@
+
+ RUN v3.2.6 Z:/Документы/PROCOLLAB-dev/procollab-dev-platform-responsive
+
+ ✓ projects/ui/src/lib/components/layout/profile-info/profile-info.component.spec.ts (1 test) 104ms
+ ✓ projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.spec.ts (1 test) 213ms
+stdout | projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.spec.ts > FeedComponent > показывает счётчики всех шести категорий независимо от фильтра
+[23:05:50.477] [DEBUG] Query change from FeedFilterComponent
+
+ ✓ projects/social_platform/src/app/ui/widgets/feed-filter/feed-filter.component.spec.ts (2 tests) 159ms
+
+ Test Files 3 passed (3)
+ Tests 4 passed (4)
+ Start at 23:05:32
+ Duration 8.12s (transform 5.94s, setup 8.08s, collect 5.88s, tests 476ms, environment 3.24s, prepare 3.87s)
+
diff --git a/docs/responsive/browser-harness.cjs b/docs/responsive/browser-harness.cjs
index 63f3306b2..fb634a509 100644
--- a/docs/responsive/browser-harness.cjs
+++ b/docs/responsive/browser-harness.cjs
@@ -3,9 +3,10 @@
const { chromium } = require(process.env.PLAYWRIGHT_MODULE || "playwright");
const assert = require("node:assert/strict");
const fixtures = require("./fixtures.cjs");
-const base = "http://127.0.0.1:4360";
+const defaultBase = "http://127.0.0.1:4360";
async function launch(width = 390, options = {}) {
+ const { baseUrl: base = defaultBase, ...contextOptions } = options;
const browser = await chromium.launch({
headless: true,
executablePath: process.env.CHROME_PATH,
@@ -13,7 +14,7 @@ async function launch(width = 390, options = {}) {
const context = await browser.newContext({
viewport: { width, height: 844 },
reducedMotion: "reduce",
- ...options,
+ ...contextOptions,
});
await context.addCookies(
["accessToken", "refreshToken", "devAccessToken", "devRefreshToken"].map(name => ({
@@ -117,4 +118,4 @@ async function assertViewport(page) {
return result;
}
-module.exports = { launch, measure, assertViewport, base };
+module.exports = { launch, measure, assertViewport, base: defaultBase };
diff --git a/docs/ui-kit/UI-KIT.md b/docs/ui-kit/UI-KIT.md
index 87a90eff5..b4e53e089 100644
--- a/docs/ui-kit/UI-KIT.md
+++ b/docs/ui-kit/UI-KIT.md
@@ -2,7 +2,17 @@
# UI Kit PROCOLLAB
-Единые компоненты находятся в `projects/ui/src/lib/components` и экспортируются через `@uilib`. FormControl-компоненты приложения остаются в `@ui/primitives`: их CVA, валидация и доменные интеграции не меняются. Старые импорты Button, Avatar, Icon, Loader и канбан Badge — реэкспорты тех же классов, без второй Angular-реализации.
+Единые компоненты находятся в `projects/ui/src/lib/components` и экспортируются через `@uilib`. FormControl-компоненты приложения остаются в `@ui/primitives`: их CVA, валидация и доменные интеграции не меняются. Старые импорты Button, Icon, Loader и канбан Badge — реэкспорты тех же классов. Social Avatar наследует inputs canonical Avatar и сохраняет прежнюю desktop presentation через compatibility adapter.
+
+## Desktop compatibility
+
+Responsive/UI Kit presentation ограничена `<1000px`. На desktop ≥1000px legacy consumers сохраняют
+композицию и геометрию `dev` до #401: общие Card/Field/Form/Filters adapters не навязывают размеры,
+отступы и сетки. Button, Icon, Avatar и PageHeader сохраняют прежние desktop contracts;
+требование 44 px для мобильных targets не увеличивает старые desktop кнопки.
+
+Перед изменениями shared styles обязательны desktop pixel comparisons на 1440/1920 и
+mobile/tablet проверки на 320/390/768: [gate, эталон и evidence](../desktop-regression/README.md).
| Семейство | Источник | Правило |
| --------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
diff --git a/projects/social_platform/src/app/ui/pages/auth/auth.component.scss b/projects/social_platform/src/app/ui/pages/auth/auth.component.scss
index b3287874c..3ddc634f4 100644
--- a/projects/social_platform/src/app/ui/pages/auth/auth.component.scss
+++ b/projects/social_platform/src/app/ui/pages/auth/auth.component.scss
@@ -11,10 +11,6 @@
@include responsive.apply-desktop {
padding: 0 200px;
-
- &:has(.login) {
- padding: 0;
- }
}
&__header {
@@ -30,16 +26,18 @@
}
}
-@include responsive.apply-below-desktop {
- .page {
- height: auto;
- min-height: 100dvh;
- padding: 0 var(--page-gutter);
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .page {
+ height: auto;
+ min-height: 100dvh;
+ padding: 0 var(--page-gutter);
+ }
- .page__body {
- justify-content: flex-start;
- height: auto;
- min-height: 100dvh;
+ .page__body {
+ justify-content: flex-start;
+ height: auto;
+ min-height: 100dvh;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.scss b/projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.scss
index 1eb44e29a..345052222 100644
--- a/projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.scss
+++ b/projects/social_platform/src/app/ui/pages/auth/email-verification/email-verification.component.scss
@@ -37,11 +37,7 @@
@include responsive.apply-desktop {
bottom: 0%;
left: 30%;
- width: min(852px, 70vw);
- min-width: 0;
- max-width: 70vw;
- max-height: 92dvh;
- object-fit: contain;
+ min-width: 852px;
}
}
@@ -56,17 +52,19 @@
}
}
-@include responsive.apply-below-desktop {
- .verification__img {
- position: static;
- width: 100%;
- min-width: 0;
- max-height: 40dvh;
- object-fit: contain;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .verification__img {
+ position: static;
+ width: 100%;
+ min-width: 0;
+ max-height: 40dvh;
+ object-fit: contain;
+ }
- .verification__action {
- flex-wrap: wrap;
- gap: 12px;
+ .verification__action {
+ flex-wrap: wrap;
+ gap: 12px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/auth/login/login.component.scss b/projects/social_platform/src/app/ui/pages/auth/login/login.component.scss
index c4da6f77a..775482494 100644
--- a/projects/social_platform/src/app/ui/pages/auth/login/login.component.scss
+++ b/projects/social_platform/src/app/ui/pages/auth/login/login.component.scss
@@ -5,20 +5,28 @@
.login {
display: flex;
- width: 100%;
- min-width: 0;
- min-height: 100vh;
+
+ @media screen and (max-width: 999px) {
+ width: 100%;
+ min-width: 0;
+ min-height: 100vh;
+ }
+
+ @media screen and (min-width: 1000px) {
+ min-width: 95vw;
+ min-height: 100vh;
+ }
&__left {
display: flex;
flex: 1;
flex-direction: column;
- min-width: 0;
- padding-left: 10px;
- @include responsive.apply-desktop {
- padding-left: clamp(32px, 14vw, 200px);
+ @media screen and (max-width: 999px) {
+ min-width: 0;
}
+
+ padding-left: 10px;
}
&__left-content {
@@ -124,37 +132,39 @@
cursor: pointer;
}
-@include responsive.apply-below-desktop {
- .login {
- width: 100%;
- min-width: 0;
- min-height: 100dvh;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .login {
+ width: 100%;
+ min-width: 0;
+ min-height: 100dvh;
+ }
- .login__left {
- min-width: 0;
- padding-left: 0;
- }
+ .login__left {
+ min-width: 0;
+ padding-left: 0;
+ }
- .login__left-content {
- padding: 24px 0;
- }
+ .login__left-content {
+ padding: 24px 0;
+ }
- .login .auth__wrapper {
- width: 100%;
- max-width: none;
- }
+ .login .auth__wrapper {
+ width: 100%;
+ max-width: none;
+ }
- .login__password {
- flex-wrap: wrap;
- gap: 12px;
- }
+ .login__password {
+ flex-wrap: wrap;
+ gap: 12px;
+ }
- .tooltip__wrapper {
- position: fixed;
- right: var(--page-gutter);
- bottom: max(16px, env(safe-area-inset-bottom));
- left: var(--page-gutter);
- width: auto;
+ .tooltip__wrapper {
+ position: fixed;
+ right: var(--page-gutter);
+ bottom: max(16px, env(safe-area-inset-bottom));
+ left: var(--page-gutter);
+ width: auto;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.scss b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.scss
index a9905591a..9e97fb9c1 100644
--- a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.scss
+++ b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/exclude-task/exclude-task.component.scss
@@ -14,14 +14,6 @@
gap: 20px;
}
- /* &--hasContent { */
-
- /* display: flex; */
-
- /* flex-direction: row-reverse; */
-
- /* } */
-
&__answer {
color: var(--grey-for-text);
}
@@ -176,4 +168,6 @@
}
}
-@include course-task.responsive-layout("exclude");
+@media screen and (max-width: 999px) {
+ @include course-task.responsive-layout("exclude");
+}
diff --git a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/file-task/file-task.component.scss b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/file-task/file-task.component.scss
index d5c0e6515..9f2785e3c 100644
--- a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/file-task/file-task.component.scss
+++ b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/file-task/file-task.component.scss
@@ -1,3 +1,5 @@
+/** @format */
+
@use "styles/course-task";
@use "styles/responsive";
@use "styles/typography";
@@ -203,4 +205,6 @@
}
}
-@include course-task.responsive-layout("file-task");
+@media screen and (max-width: 999px) {
+ @include course-task.responsive-layout("file-task");
+}
diff --git a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.scss b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.scss
index 3444e8a2b..02d7fc8b7 100644
--- a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.scss
+++ b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/radio-select-task/radio-select-task.component.scss
@@ -12,12 +12,6 @@
@include responsive.apply-desktop {
flex-direction: row;
gap: 20px;
-
- /* &--hasContent { */
-
- /* flex-direction: row-reverse; */
-
- /* } */
}
&__answer {
@@ -195,21 +189,25 @@
}
}
-@include responsive.apply-mobile {
- .radio__item {
- min-width: 0;
- min-height: 44px;
- padding: 4px 0;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .radio__item {
+ min-width: 0;
+ min-height: 44px;
+ padding: 4px 0;
+ }
- .radio__item input {
- flex-shrink: 0;
- }
+ .radio__item input {
+ flex-shrink: 0;
+ }
- .radio__item label {
- min-width: 0;
- overflow-wrap: anywhere;
+ .radio__item label {
+ min-width: 0;
+ overflow-wrap: anywhere;
+ }
}
}
-@include course-task.responsive-layout("radio");
+@media screen and (max-width: 999px) {
+ @include course-task.responsive-layout("radio");
+}
diff --git a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/video-task/info-task.component.scss b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/video-task/info-task.component.scss
index bb4028444..5cec502c3 100644
--- a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/video-task/info-task.component.scss
+++ b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/video-task/info-task.component.scss
@@ -1,3 +1,5 @@
+/** @format */
+
@use "styles/course-task";
@use "styles/responsive";
@@ -114,4 +116,6 @@
}
}
-@include course-task.responsive-layout("video");
+@media screen and (max-width: 999px) {
+ @include course-task.responsive-layout("video");
+}
diff --git a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.scss b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.scss
index 1cfc2352d..8c33ebfa7 100644
--- a/projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.scss
+++ b/projects/social_platform/src/app/ui/pages/courses/lesson/shared/write-task/write-task.component.scss
@@ -1,3 +1,5 @@
+/** @format */
+
@use "styles/course-task";
@use "styles/responsive";
@@ -178,4 +180,6 @@
}
}
-@include course-task.responsive-layout("write-task");
+@media screen and (max-width: 999px) {
+ @include course-task.responsive-layout("write-task");
+}
diff --git a/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.html b/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.html
index b3b048a50..68e8192f4 100644
--- a/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.html
+++ b/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.html
@@ -4,17 +4,33 @@
-
+ @if (desktopLayout()) {
+
+ {{
+ isMember()
+ ? "для участников программы"
+ : isSubs()
+ ? "доступно по подписке"
+ : "доступно всем пользователям"
+ }}
+
+ } @else {
+
+ }
diff --git a/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss b/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss
index 809b09d6f..ca983f44d 100644
--- a/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss
+++ b/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.scss
@@ -5,7 +5,11 @@
@use "styles/typography";
.course {
- @include ui-foundation.card;
+ @media screen and (max-width: 999px) {
+ @include ui-foundation.card;
+
+ max-width: 333px;
+ }
position: relative;
width: 100%;
@@ -13,8 +17,49 @@
overflow: hidden;
cursor: pointer;
+ @media screen and (min-width: 1000px) {
+ background-color: var(--light-white);
+ }
+
+ @media screen and (min-width: 1000px) {
+ border: 0.5px solid var(--medium-grey-for-outline);
+ }
+
+ @media screen and (min-width: 1000px) {
+ border-radius: var(--rounded-lg);
+ }
+
&__cover {
border-radius: var(--rounded-lg);
+
+ @media screen and (min-width: 1000px) {
+ app-button {
+ ::ng-deep {
+ .button {
+ position: absolute;
+ top: 15px;
+ right: 24px;
+ width: 166px;
+ padding: 0;
+ }
+ }
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ app-avatar {
+ ::ng-deep {
+ .avatar {
+ img {
+ position: absolute;
+ top: 35px;
+ left: 24px;
+ box-shadow: 0 0 8px rgba($color: #333, $alpha: 30%);
+ }
+ }
+ }
+ }
+ }
}
&__image {
@@ -66,18 +111,22 @@
}
}
-.course__cover app-avatar {
- position: absolute;
- top: 35px;
- left: 24px;
- z-index: 1;
- border-radius: 50%;
- box-shadow: var(--ui-card-hover-shadow);
+@media screen and (max-width: 999px) {
+ .course__cover app-avatar {
+ position: absolute;
+ top: 35px;
+ left: 24px;
+ z-index: 1;
+ border-radius: 50%;
+ box-shadow: var(--ui-card-hover-shadow);
+ }
}
-.course__access {
- position: absolute;
- top: 15px;
- right: 24px;
- max-width: 166px;
+@media screen and (max-width: 999px) {
+ .course__access {
+ position: absolute;
+ top: 15px;
+ right: 24px;
+ max-width: 166px;
+ }
}
diff --git a/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.ts b/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.ts
index a3d255ed5..642af949d 100644
--- a/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.ts
+++ b/projects/social_platform/src/app/ui/pages/courses/list/course/course.component.ts
@@ -1,10 +1,18 @@
/** @format */
-import { CardDirective, BadgeComponent } from "@uilib";
+import { DesktopLayoutService, CardDirective, BadgeComponent } from "@uilib";
/** @format */
import { CommonModule } from "@angular/common";
-import { ChangeDetectionStrategy, Component, input, Input, OnInit, signal } from "@angular/core";
+import {
+ ChangeDetectionStrategy,
+ Component,
+ inject,
+ input,
+ Input,
+ OnInit,
+ signal,
+} from "@angular/core";
import { RouterModule } from "@angular/router";
import { IconComponent, ButtonComponent } from "@ui/primitives";
import { AvatarComponent } from "@ui/primitives/avatar/avatar.component";
@@ -36,6 +44,7 @@ import { TruncatePipe } from "@corelib";
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CourseComponent implements OnInit {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
readonly course = input.required
();
ngOnInit(): void {
diff --git a/projects/social_platform/src/app/ui/pages/courses/list/list.component.html b/projects/social_platform/src/app/ui/pages/courses/list/list.component.html
index beae97dae..85016ce40 100644
--- a/projects/social_platform/src/app/ui/pages/courses/list/list.component.html
+++ b/projects/social_platform/src/app/ui/pages/courses/list/list.component.html
@@ -2,7 +2,11 @@
@if (loading()) {
-
+ @if (desktopLayout()) {
+
+ } @else {
+
+ }
} @else if (coursesList().length) {
@for (course of coursesList(); track course.id) {
@@ -12,6 +16,8 @@
}
} @else {
-
+ @if (!desktopLayout()) {
+
+ }
}
diff --git a/projects/social_platform/src/app/ui/pages/courses/list/list.component.ts b/projects/social_platform/src/app/ui/pages/courses/list/list.component.ts
index 7794dcce6..7fba4fd49 100644
--- a/projects/social_platform/src/app/ui/pages/courses/list/list.component.ts
+++ b/projects/social_platform/src/app/ui/pages/courses/list/list.component.ts
@@ -1,6 +1,6 @@
/** @format */
-import { StateComponent } from "@uilib";
+import { DesktopLayoutService, StateComponent } from "@uilib";
/** @format */
import { ChangeDetectionStrategy, Component, inject, OnInit } from "@angular/core";
@@ -22,6 +22,7 @@ import { AppRoutes } from "@api/paths/app-routes";
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoursesListComponent implements OnInit {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
private readonly coursesListInfoService = inject(CoursesListInfoService);
private readonly coursesListUIInfoService = inject(CoursesListUIInfoService);
diff --git a/projects/social_platform/src/app/ui/pages/error/error-code/error-code.component.scss b/projects/social_platform/src/app/ui/pages/error/error-code/error-code.component.scss
index 408198756..6c671a8e7 100644
--- a/projects/social_platform/src/app/ui/pages/error/error-code/error-code.component.scss
+++ b/projects/social_platform/src/app/ui/pages/error/error-code/error-code.component.scss
@@ -15,12 +15,19 @@
height: 580px;
margin-bottom: 20px;
color: var(--error-code);
- background:
- radial-gradient(
- 50% 50% at 50% 50%,
- var(--ui-success-glow) 0%,
- var(--ui-success-glow-end) 100%
- );
+
+ @media screen and (max-width: 999px) {
+ background:
+ radial-gradient(
+ 50% 50% at 50% 50%,
+ var(--ui-success-glow) 0%,
+ var(--ui-success-glow-end) 100%
+ );
+ }
+
+ @media screen and (min-width: 1000px) {
+ background: radial-gradient(50% 50% at 50% 50%, rgb(0 200 147 / 51%) 0%, rgb(0 200 147 / 0%) 100%);
+ }
}
&__title {
@@ -35,24 +42,26 @@
}
}
-@include responsive.apply-below-desktop {
- .error {
- padding: 24px var(--page-gutter);
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .error {
+ padding: 24px var(--page-gutter);
+ }
- .error__body {
- width: 100%;
- min-width: 0;
- }
+ .error__body {
+ width: 100%;
+ min-width: 0;
+ }
- .error__code {
- width: 100%;
- height: auto;
- min-height: 240px;
- font-size: clamp(96px, 30vw, 240px);
- }
+ .error__code {
+ width: 100%;
+ height: auto;
+ min-height: 240px;
+ font-size: clamp(96px, 30vw, 240px);
+ }
- .error__link {
- min-height: 44px;
+ .error__link {
+ min-height: 44px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/feed/feed.component.html b/projects/social_platform/src/app/ui/pages/feed/feed.component.html
index c4a83e34c..ba9368ea4 100644
--- a/projects/social_platform/src/app/ui/pages/feed/feed.component.html
+++ b/projects/social_platform/src/app/ui/pages/feed/feed.component.html
@@ -34,7 +34,14 @@
}
}
} @else {
-
+ @if (desktopLayout()) {
+
+
+
в данном разделе пока нет новостей
+
+ } @else {
+
+ }
}
diff --git a/projects/social_platform/src/app/ui/pages/feed/feed.component.scss b/projects/social_platform/src/app/ui/pages/feed/feed.component.scss
index 9450e77a6..1fbddad33 100644
--- a/projects/social_platform/src/app/ui/pages/feed/feed.component.scss
+++ b/projects/social_platform/src/app/ui/pages/feed/feed.component.scss
@@ -41,6 +41,11 @@
}
@include responsive.apply-below-desktop {
+ .page {
+ padding-top: 24px;
+ margin: 0 var(--page-gutter);
+ }
+
.filter {
position: fixed;
z-index: 300;
diff --git a/projects/social_platform/src/app/ui/pages/feed/feed.component.ts b/projects/social_platform/src/app/ui/pages/feed/feed.component.ts
index 31d4e1838..2ce41490d 100644
--- a/projects/social_platform/src/app/ui/pages/feed/feed.component.ts
+++ b/projects/social_platform/src/app/ui/pages/feed/feed.component.ts
@@ -1,6 +1,6 @@
/** @format */
-import { StateComponent } from "@uilib";
+import { DesktopLayoutService, StateComponent } from "@uilib";
/** @format */
import {
@@ -42,6 +42,7 @@ import { FeedItem } from "@domain/feed/feed-item.model";
providers: [FeedInfoService, FeedUIInfoService, ProjectTeamUIService],
})
export class FeedComponent implements AfterViewInit, OnDestroy {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
readonly feedRoot = viewChild>("feedRoot");
private readonly feedInfoService = inject(FeedInfoService);
diff --git a/projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.html b/projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.html
index c4ee6e578..27501fc5f 100644
--- a/projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.html
+++ b/projects/social_platform/src/app/ui/pages/feed/open-vacancy/open-vacancy.component.html
@@ -29,21 +29,25 @@ {{ feedItem()
>
}
+
}
diff --git a/projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss b/projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss
index 8a5bf28dd..06e059c65 100644
--- a/projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss
+++ b/projects/social_platform/src/app/ui/pages/office/nav/nav.component.scss
@@ -3,6 +3,12 @@
@use "styles/responsive";
@use "styles/typography";
+@media screen and (max-width: 999px) {
+ .nav-bar__logout {
+ margin-top: auto;
+ }
+}
+
.nav-bar {
display: block;
@@ -13,10 +19,26 @@
}
&__inner {
- display: flex;
- gap: 8px;
- align-items: center;
- justify-content: space-between;
+ @media screen and (max-width: 999px) {
+ display: grid;
+ }
+
+ @media screen and (min-width: 1000px) {
+ display: flex;
+ }
+
+ @media screen and (max-width: 999px) {
+ grid-template-columns: 88px minmax(0, 1fr) 88px;
+ }
+
+ @media screen and (max-width: 999px) {
+ align-items: center;
+ }
+
+ @media screen and (min-width: 1000px) {
+ justify-content: space-between;
+ }
+
max-width: responsive.$container-md;
margin: 0 auto;
@@ -47,9 +69,18 @@
cursor: pointer;
border-radius: var(--rounded-sm);
- > .attention {
- top: 9px;
- right: 11px;
+ @media screen and (max-width: 999px) {
+ > .attention {
+ top: 9px;
+ right: 11px;
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ >.attention {
+ top: 9px;
+ right: 11px;
+ }
}
&--active {
@@ -61,17 +92,49 @@
&__toggle {
position: relative;
z-index: 100;
- display: flex;
- flex-shrink: 0;
- align-items: center;
- justify-content: center;
- width: 44px;
- height: 44px;
+
+ @media screen and (max-width: 999px) {
+ display: flex;
+ }
+
+ @media screen and (min-width: 1000px) {
+ display: block;
+ }
+
+ @media screen and (max-width: 999px) {
+ flex-shrink: 0;
+ }
+
+ @media screen and (max-width: 999px) {
+ align-items: center;
+ }
+
+ @media screen and (max-width: 999px) {
+ justify-content: center;
+ }
+
+ @media screen and (max-width: 999px) {
+ width: 44px;
+ }
+
+ @media screen and (max-width: 999px) {
+ height: 44px;
+ }
+
cursor: pointer;
- > .attention {
- top: 8px;
- right: 2px;
+ @media screen and (max-width: 999px) {
+ > .attention {
+ top: 8px;
+ right: 2px;
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ >.attention {
+ top: 8px;
+ right: 2px;
+ }
}
@include responsive.apply-desktop {
@@ -84,48 +147,72 @@
top: 0;
bottom: 0;
left: 0;
- z-index: 201;
display: flex;
flex-direction: column;
- width: min(360px, calc(100% - 32px));
- max-height: 100dvh;
- padding: max(16px, env(safe-area-inset-top)) 16px max(24px, env(safe-area-inset-bottom));
- overflow-y: auto;
- overscroll-behavior: contain;
background-color: var(--white);
+
+ @media screen and (max-width: 999px) {
+ z-index: 201;
+ width: min(360px, calc(100% - 32px));
+ max-height: 100dvh;
+ padding: max(16px, env(safe-area-inset-top)) 16px max(24px, env(safe-area-inset-bottom));
+ overflow-y: auto;
+ overscroll-behavior: contain;
+ }
+
+ @media screen and (min-width: 1000px) {
+ right: 0;
+ z-index: 50;
+ padding: 25px 15px 30px;
+ }
}
- &__backdrop {
- position: fixed;
- inset: 0;
- z-index: 200;
- background: var(--ui-scrim);
+ @media screen and (max-width: 999px) {
+ &__backdrop {
+ position: fixed;
+ inset: 0;
+ z-index: 200;
+ background: var(--ui-scrim);
+ }
}
- &__close {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 44px;
- height: 44px;
- margin-right: auto;
- color: var(--dark-grey);
- cursor: pointer;
+ @media screen and (max-width: 999px) {
+ &__close {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 44px;
+ height: 44px;
+ margin-right: auto;
+ color: var(--dark-grey);
+ cursor: pointer;
+ }
}
- &__title {
- min-width: 0;
- color: var(--white);
- overflow-wrap: anywhere;
+ @media screen and (max-width: 999px) {
+ &__title {
+ grid-row: 1;
+ grid-column: 2;
+ min-width: 0;
+ font-weight: 600;
+ line-height: 18px;
+ color: var(--ui-text);
+ text-align: center;
+ overflow-wrap: anywhere;
+ }
}
- ::ng-deep .nav__link {
- width: 100%;
- margin-bottom: 12px;
+ @media screen and (max-width: 999px) {
+ ::ng-deep .nav__link {
+ width: 100%;
+ margin-bottom: 12px;
+ }
}
- ::ng-deep .nav__item {
- min-height: 44px;
+ @media screen and (max-width: 999px) {
+ ::ng-deep .nav__item {
+ min-height: 44px;
+ }
}
&__user {
diff --git a/projects/social_platform/src/app/ui/pages/office/nav/nav.component.ts b/projects/social_platform/src/app/ui/pages/office/nav/nav.component.ts
index da9e3de2e..97e35dca5 100644
--- a/projects/social_platform/src/app/ui/pages/office/nav/nav.component.ts
+++ b/projects/social_platform/src/app/ui/pages/office/nav/nav.component.ts
@@ -21,10 +21,17 @@ import {
OnDestroy,
OnInit,
inject,
+ output,
} from "@angular/core";
import { AsyncPipe, CommonModule } from "@angular/common";
import { IconComponent } from "@ui/primitives";
-import { NavigationStart, Router, RouterLink, RouterLinkActive } from "@angular/router";
+import {
+ NavigationEnd,
+ NavigationStart,
+ Router,
+ RouterLink,
+ RouterLinkActive,
+} from "@angular/router";
import { NavService } from "@api/shared/nav.service";
import { InviteInfoService } from "@api/invite/facades/invite-info.service";
import { A11yModule } from "@angular/cdk/a11y";
@@ -86,6 +93,7 @@ export class NavComponent implements OnInit, OnDestroy {
private menuTrigger?: HTMLElement;
readonly invites = this.inviteInfoService.invites;
+ readonly logout = output();
constructor(
private readonly router: Router,
@@ -96,17 +104,22 @@ export class NavComponent implements OnInit, OnDestroy {
) {}
ngOnInit(): void {
+ this.title = this.routeTitle(this.router.url);
// Подписка на события роутера для закрытия мобильного меню
this.router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(event => {
if (event instanceof NavigationStart) {
this.closeMenu();
this.cdref.markForCheck();
}
+ if (event instanceof NavigationEnd) {
+ this.title = this.routeTitle(event.urlAfterRedirects) || this.title;
+ this.cdref.markForCheck();
+ }
});
// Подписка на изменения заголовка страницы
this.navService.navTitle.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(title => {
- this.title = title;
+ this.title = this.routeTitle(this.router.url) || title;
this.cdref.detectChanges();
});
}
@@ -115,6 +128,25 @@ export class NavComponent implements OnInit, OnDestroy {
this.menuScrollStrategy.disable();
}
+ private routeTitle(url: string): string {
+ const path = url.split(/[?#]/)[0];
+ if (/^\/office\/profile\/edit(?:\/|$)/.test(path)) return "Редактирование профиля";
+ if (/^\/office\/projects\/create(?:\/|$)/.test(path)) return "Создание проекта";
+ if (/^\/office\/projects\/\d+\/edit(?:\/|$)/.test(path)) return "Редактирование проекта";
+ if (/^\/office\/projects\/\d+(?:\/|$)/.test(path)) return "Профиль проекта";
+ const sections: Record = {
+ feed: "Новости",
+ projects: "Проекты",
+ members: "Участники",
+ program: "Программы",
+ courses: "Курсы",
+ vacancies: "Вакансии",
+ profile: "Профиль",
+ chats: "Чаты",
+ };
+ return sections[path.split("/")[2]] || "";
+ }
+
@HostListener("window:resize")
onViewportResize(): void {
if (this.mobileMenuOpen && window.innerWidth >= desktop) this.closeMenu();
diff --git a/projects/social_platform/src/app/ui/pages/office/office.component.html b/projects/social_platform/src/app/ui/pages/office/office.component.html
index 5f840178f..ce1d59b4b 100644
--- a/projects/social_platform/src/app/ui/pages/office/office.component.html
+++ b/projects/social_platform/src/app/ui/pages/office/office.component.html
@@ -39,7 +39,7 @@
-
+
@if (profile() !== undefined && invites() !== undefined) {
app-nav {
- flex: 1;
- min-width: 0;
+ @media screen and (max-width: 999px) {
+ &__top > app-nav {
+ grid-row: 1;
+ grid-column: 1 / -1;
+ min-width: 0;
+ }
+ }
+
+ @media screen and (max-width: 999px) {
+ &__top > app-profile-control-panel {
+ grid-row: 1;
+ grid-column: 3;
+ justify-self: end;
+ min-width: 0;
+ }
}
&__header {
diff --git a/projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.scss b/projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.scss
index d6da495e1..60046c083 100644
--- a/projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.scss
+++ b/projects/social_platform/src/app/ui/pages/office/snackbar/snackbar.component.scss
@@ -2,8 +2,6 @@
@use "styles/responsive";
-/** @format */
-
.snackbar {
position: absolute;
top: 0;
@@ -13,7 +11,15 @@
padding-right: 50px;
overflow-x: hidden;
+ @media screen and (max-width: 999px) {
+ pointer-events: none;
+ }
+
&__item {
+ @media screen and (max-width: 999px) {
+ pointer-events: auto;
+ }
+
&:not(:last-child) {
margin-bottom: 10px;
}
@@ -44,20 +50,22 @@
}
}
-@include responsive.apply-mobile {
- .snackbar {
- position: fixed;
- top: max(12px, env(safe-area-inset-top));
- right: var(--page-gutter);
- left: var(--page-gutter);
- max-height: calc(100dvh - 24px);
- padding: 0;
- overflow-y: auto;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .snackbar {
+ position: fixed;
+ top: max(12px, env(safe-area-inset-top));
+ right: var(--page-gutter);
+ left: var(--page-gutter);
+ max-height: calc(100dvh - 24px);
+ padding: 0;
+ overflow-y: auto;
+ }
- .item {
- min-width: 0;
- padding: 12px;
- overflow-wrap: anywhere;
+ .item {
+ min-width: 0;
+ padding: 12px;
+ overflow-wrap: anywhere;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.scss b/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.scss
index b7d5313f6..ae0c8110d 100644
--- a/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-left-side/profile-left-side.component.scss
@@ -111,8 +111,8 @@
background-color: var(--accent-light);
}
- /* stylelint-disable value-no-vendor-prefix */
&__program-name {
+ /* stylelint-disable-next-line value-no-vendor-prefix */
display: -webkit-box;
min-width: 0;
overflow: hidden;
@@ -122,14 +122,21 @@
-webkit-line-clamp: 2;
&--compact {
- font-size: var(--ui-font-caption);
- font-weight: 400;
line-height: 14px;
word-break: normal;
overflow-wrap: normal;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ font-weight: 400;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 10px;
+ font-weight: 400;
+ }
}
}
- /* stylelint-enable value-no-vendor-prefix */
&__icon {
color: var(--accent);
diff --git a/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.scss b/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.scss
index a8d873e0b..98008d770 100644
--- a/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/detail/main/components/profile-right-side/profile-right-side.component.scss
@@ -107,17 +107,31 @@
}
&--subtext {
- font-size: var(--ui-font-caption);
line-height: 16px;
color: var(--grey-for-text) !important;
word-break: break-word;
overflow-wrap: anywhere;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 11px;
+ }
}
&--more {
- font-size: var(--ui-font-caption);
line-height: 16px;
color: var(--accent) !important;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 11px;
+ }
}
img {
@@ -125,8 +139,8 @@
}
}
- /* stylelint-disable value-no-vendor-prefix */
&__project-name {
+ /* stylelint-disable-next-line value-no-vendor-prefix */
display: -webkit-box;
overflow: hidden;
font-size: var(--ui-font-small);
@@ -140,12 +154,18 @@
&__project-role {
margin-top: 3px;
- font-size: var(--ui-font-caption);
line-height: 15px;
color: var(--dark-grey);
overflow-wrap: anywhere;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 11px;
+ }
}
- /* stylelint-enable value-no-vendor-prefix */
&__date {
display: flex;
@@ -158,9 +178,16 @@
border-radius: var(--rounded-xl);
p {
- font-size: var(--ui-font-caption);
line-height: 14px;
color: var(--dark-grey);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 11px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/profile/detail/profile-news/profile-news.component.scss b/projects/social_platform/src/app/ui/pages/profile/detail/profile-news/profile-news.component.scss
index 0219fccd0..3195861cc 100644
--- a/projects/social_platform/src/app/ui/pages/profile/detail/profile-news/profile-news.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/detail/profile-news/profile-news.component.scss
@@ -6,7 +6,6 @@
display: block;
@include responsive.apply-desktop {
- width: 100%;
- min-width: 0;
+ min-width: 800px;
}
}
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-achievements-step/profile-achievements-step.component.scss b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-achievements-step/profile-achievements-step.component.scss
index c394c4427..fab36a81e 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-achievements-step/profile-achievements-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-achievements-step/profile-achievements-step.component.scss
@@ -1,7 +1,6 @@
-@use "styles/profile-form";
-
/** @format */
+@use "styles/profile-form";
@use "styles/responsive";
.profile__wrapper--education {
@@ -119,4 +118,6 @@
}
}
-@include profile-form.responsive-layout;
+@media screen and (max-width: 999px) {
+ @include profile-form.responsive-layout;
+}
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-education-step/profile-education-step.component.scss b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-education-step/profile-education-step.component.scss
index fc3d2503b..bbf8e84bb 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-education-step/profile-education-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-education-step/profile-education-step.component.scss
@@ -1,7 +1,6 @@
-@use "styles/profile-form";
-
/** @format */
+@use "styles/profile-form";
@use "styles/responsive";
.profile__wrapper--education {
@@ -113,4 +112,6 @@
}
}
-@include profile-form.responsive-layout;
+@media screen and (max-width: 999px) {
+ @include profile-form.responsive-layout;
+}
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-experience-step/profile-experience-step.component.scss b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-experience-step/profile-experience-step.component.scss
index fc3d2503b..bbf8e84bb 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-experience-step/profile-experience-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-experience-step/profile-experience-step.component.scss
@@ -1,7 +1,6 @@
-@use "styles/profile-form";
-
/** @format */
+@use "styles/profile-form";
@use "styles/responsive";
.profile__wrapper--education {
@@ -113,4 +112,6 @@
}
}
-@include profile-form.responsive-layout;
+@media screen and (max-width: 999px) {
+ @include profile-form.responsive-layout;
+}
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.scss b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.scss
index 220ea437a..4163ebdc8 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-main-step/profile-main-step.component.scss
@@ -1,7 +1,6 @@
-@use "styles/profile-form";
-
/** @format */
+@use "styles/profile-form";
@use "styles/responsive";
.profile__wrapper--main {
@@ -114,4 +113,6 @@
margin-bottom: 10px;
}
-@include profile-form.responsive-layout;
+@media screen and (max-width: 999px) {
+ @include profile-form.responsive-layout;
+}
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-skills-step/profile-skills-step.component.scss b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-skills-step/profile-skills-step.component.scss
index 40a17ae90..bafc5d9dd 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-skills-step/profile-skills-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/components/profile-skills-step/profile-skills-step.component.scss
@@ -1,7 +1,6 @@
-@use "styles/profile-form";
-
/** @format */
+@use "styles/profile-form";
@use "styles/responsive";
:host,
@@ -129,4 +128,6 @@ fieldset {
}
}
-@include profile-form.responsive-layout;
+@media screen and (max-width: 999px) {
+ @include profile-form.responsive-layout;
+}
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.html b/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.html
index a3e98136b..64fdfabd8 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.html
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.html
@@ -2,10 +2,21 @@
@if (profileForm.get("userType"); as currentType) {
-
+ @if (desktopLayout()) {
+
+
+
редактирование профиля
+
+
+ } @else {
+
+
+
+ }
+
-
+
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.scss b/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.scss
index 108f39d41..cc72026a6 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.scss
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.scss
@@ -327,10 +327,17 @@
flex-direction: column;
gap: 20px;
align-items: center;
- width: 100%;
- min-width: 0;
- max-width: 100%;
- padding: 0;
+
+ @media screen and (max-width: 999px) {
+ width: 100%;
+ min-width: 0;
+ max-width: 100%;
+ padding: 0;
+ }
+
+ @media screen and (min-width: 1000px) {
+ width: 672px;
+ }
}
&__close {
@@ -416,32 +423,34 @@
}
}
-@include responsive.apply-below-desktop {
- :host {
- display: block;
- min-width: 0;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ :host {
+ display: block;
+ min-width: 0;
+ }
- .profile {
- padding: 16px var(--page-gutter) max(24px, env(safe-area-inset-bottom));
- }
+ .profile {
+ padding: 16px var(--page-gutter) max(24px, env(safe-area-inset-bottom));
+ }
- .profile__top {
- position: static;
- gap: 12px;
- justify-content: space-between;
- padding: 8px var(--page-gutter);
- }
+ .profile__top {
+ position: static;
+ gap: 12px;
+ justify-content: space-between;
+ padding: 8px var(--page-gutter);
+ }
- .profile__left form {
- width: 100%;
- }
+ .profile__left form {
+ width: 100%;
+ }
- .profile__save {
- @include responsive.mobile-actions;
- }
+ .profile__save {
+ @include responsive.mobile-actions;
+ }
- .profile__wrapper--settings {
- min-width: 0;
+ .profile__wrapper--settings {
+ min-width: 0;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.ts b/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.ts
index af9259bc4..63f9fb9b1 100644
--- a/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.ts
+++ b/projects/social_platform/src/app/ui/pages/profile/edit/edit.component.ts
@@ -1,6 +1,11 @@
/** @format */
-import { ButtonDirective, FormLayoutDirective, PageHeaderComponent } from "@uilib";
+import {
+ ButtonDirective,
+ DesktopLayoutService,
+ FormLayoutDirective,
+ PageHeaderComponent,
+} from "@uilib";
/** @format */
import {
@@ -93,6 +98,7 @@ import { ProfileEditAchievementsInfoService } from "@api/profile/facades/edit/pr
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProfileEditComponent implements OnInit, AfterViewInit {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
private readonly profileFormService = inject(ProfileFormService);
private readonly profileEditInfoService = inject(ProfileEditInfoService);
private readonly projectStepService = inject(ProjectStepService);
diff --git a/projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.scss b/projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.scss
index 1e304f650..91cb4e3be 100644
--- a/projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.scss
+++ b/projects/social_platform/src/app/ui/pages/program/detail/analytics/analytics.component.scss
@@ -208,10 +208,18 @@
&__value {
display: block;
margin-top: 6px;
- font-size: var(--ui-font-h1);
- font-weight: 700;
line-height: 1;
color: var(--black);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-h1);
+ font-weight: 700;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 24px;
+ font-weight: 700;
+ }
}
&--skeleton {
@@ -258,10 +266,18 @@
}
&__section-label {
- font-size: var(--ui-font-body);
- font-weight: 600;
line-height: 18px;
color: var(--black);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ font-weight: 600;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ font-weight: 600;
+ }
}
}
@@ -279,7 +295,6 @@
max-height: 380px;
@include responsive.apply-desktop {
- /* Let the evaluation card size the row; keep the case list scrolling inside it. */
align-self: stretch;
max-height: none;
contain: size;
@@ -341,7 +356,7 @@
}
&__name {
- /* stylelint-disable-next-line value-no-vendor-prefix -- Required for two-line clamp. */
+ /* stylelint-disable-next-line value-no-vendor-prefix */
display: -webkit-box;
min-width: 0;
overflow: hidden;
@@ -363,17 +378,33 @@
}
&__total-value {
- font-size: var(--ui-font-h2);
- font-weight: 700;
line-height: 20px;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-h2);
+ font-weight: 700;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 17px;
+ font-weight: 700;
+ }
}
&__total-label,
&__meta {
- font-size: var(--ui-font-caption);
- font-weight: 500;
line-height: 16px;
color: var(--dark-grey);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ font-weight: 500;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 10px;
+ font-weight: 500;
+ }
}
&__bar {
@@ -470,10 +501,18 @@
}
strong {
- font-size: var(--ui-font-h2);
- font-weight: 700;
line-height: 20px;
color: var(--black);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-h2);
+ font-weight: 700;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 17px;
+ font-weight: 700;
+ }
}
}
@@ -569,8 +608,15 @@
color: var(--dark-grey);
strong {
- font-size: var(--ui-font-body);
color: var(--black);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ }
}
.text-body-10 {
@@ -851,8 +897,15 @@
span {
position: absolute;
- font-size: var(--ui-font-caption);
transform: translateX(-50%);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 11px;
+ }
}
}
}
diff --git a/projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.scss b/projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.scss
index be07e5b72..b0d3775ba 100644
--- a/projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.scss
+++ b/projects/social_platform/src/app/ui/pages/program/detail/analytics/drilldown/analytics-drilldown.component.scss
@@ -1,13 +1,20 @@
/** @format */
+
@use "styles/responsive";
-/* Только case-вариант: shared modal задаёт width своим stylesheet после подключения overlay. */
.modal__body.analytics-drilldown-body.analytics-drilldown-body--case {
box-sizing: border-box;
width: min(880px, calc(100% - 24px));
- max-height: calc(var(--visual-viewport-height, 100dvh) - 32px);
padding: 20px;
overflow-y: auto;
+
+ @media screen and (max-width: 999px) {
+ max-height: calc(var(--visual-viewport-height, 100dvh) - 32px);
+ }
+
+ @media screen and (min-width: 1000px) {
+ max-height: calc(100dvh - 32px);
+ }
}
.analytics-case {
@@ -102,7 +109,7 @@
}
th {
- font-size: var(--ui-font-body);
+ font-size: 13px;
}
th:first-child,
@@ -128,16 +135,21 @@
}
}
-/* Overlay лежит вне host: единственное глобальное правило ограничено собственным bodyClass. */
.modal__body.analytics-drilldown-body {
box-sizing: border-box;
width: min(880px, calc(100vw - 24px));
- max-height: calc(var(--visual-viewport-height, 100dvh) - 32px);
padding: 20px;
overflow-y: auto;
+
+ @media screen and (max-width: 999px) {
+ max-height: calc(var(--visual-viewport-height, 100dvh) - 32px);
+ }
+
+ @media screen and (min-width: 1000px) {
+ max-height: calc(100dvh - 32px);
+ }
}
-/* Тот же шаблон используется в backlog: оформление меняется только у трёх списков назначений. */
.modal__body.analytics-drilldown-body.analytics-drilldown-body--assignments {
width: min(980px, calc(100vw - 32px));
padding: 16px;
@@ -151,8 +163,15 @@
margin-bottom: 24px;
h2 {
- font-size: var(--ui-font-h1);
line-height: 30px;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-h1);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 24px;
+ }
}
}
@@ -446,7 +465,7 @@
}
th {
- font-size: var(--ui-font-body);
+ font-size: 13px;
font-weight: 600;
}
@@ -520,9 +539,17 @@
.analytics-drilldown__action {
padding: 4px 0;
- font-size: var(--ui-font-body);
- font-weight: 500;
line-height: 20px;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ font-weight: 500;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ font-weight: 500;
+ }
}
@include responsive.apply-desktop {
diff --git a/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss b/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss
index 53f7b4266..f3ab345b7 100644
--- a/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss
+++ b/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.scss
@@ -138,9 +138,19 @@
&__tooltip {
position: fixed;
- right: calc((100vw - 1080px) / 2);
bottom: 24px;
z-index: 30;
+
+ @media screen and (max-width: 999px) {
+ right: calc((100vw - 1080px) / 2);
+ }
+
+ @media screen and (min-width: 1000px) {
+ right:
+ calc(
+ (100vw - 1080px) / 2
+ );
+ }
}
}
@@ -265,11 +275,33 @@
flex-direction: column;
align-items: center;
justify-content: center;
- width: 100%;
- min-width: 0;
- max-width: 100%;
+
+ @media screen and (max-width: 999px) {
+ width: 100%;
+ }
+
+ @media screen and (min-width: 1000px) {
+ width: 80%;
+ }
+
+ @media screen and (max-width: 999px) {
+ min-width: 0;
+ }
+
+ @media screen and (max-width: 999px) {
+ max-width: 100%;
+ }
+
max-height: calc(100vh - 40px);
- padding: 0;
+
+ @media screen and (max-width: 999px) {
+ padding: 0;
+ }
+
+ @media screen and (min-width: 1000px) {
+ padding: 0 24px;
+ }
+
overflow-y: auto;
@include responsive.apply-desktop {
@@ -313,39 +345,43 @@
}
}
-@include responsive.apply-mobile {
- .page__list {
- @include responsive.single-column;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .page__list {
+ @include responsive.single-column;
+ }
- .page__mobile-filter-row {
- @include responsive.mobile-actions;
- }
+ .page__mobile-filter-row {
+ @include responsive.mobile-actions;
+ }
- .page__tooltip {
- right: var(--page-gutter);
- bottom: max(16px, env(safe-area-inset-bottom));
- }
+ .page__tooltip {
+ right: var(--page-gutter);
+ bottom: max(16px, env(safe-area-inset-bottom));
+ }
- .tooltip__wrapper {
- position: fixed;
- right: var(--page-gutter);
- bottom: 60px;
- left: auto;
- width: calc(100vw - 2 * var(--page-gutter));
+ .tooltip__wrapper {
+ position: fixed;
+ right: var(--page-gutter);
+ bottom: 60px;
+ left: auto;
+ width: calc(100vw - 2 * var(--page-gutter));
+ }
}
}
-@include responsive.apply-below-desktop {
- .filter {
- position: fixed;
- z-index: 300;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .filter {
+ position: fixed;
+ z-index: 300;
+ }
- .filter__body {
- min-height: 0;
- max-height: calc(var(--visual-viewport-height, 100dvh) - 80px);
- padding-bottom: env(safe-area-inset-bottom, 0);
- overscroll-behavior: contain;
+ .filter__body {
+ min-height: 0;
+ max-height: calc(var(--visual-viewport-height, 100dvh) - 80px);
+ padding-bottom: env(safe-area-inset-bottom, 0);
+ overscroll-behavior: contain;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/boolean-criterion/boolean-criterion.component.scss b/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/boolean-criterion/boolean-criterion.component.scss
index 500b43267..09137139f 100644
--- a/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/boolean-criterion/boolean-criterion.component.scss
+++ b/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/boolean-criterion/boolean-criterion.component.scss
@@ -6,11 +6,13 @@
display: block;
}
-@include responsive.apply-mobile {
- .container {
- justify-content: center;
- min-width: 44px;
- min-height: 44px;
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .container {
+ justify-content: center;
+ min-width: 44px;
+ min-height: 44px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.scss b/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.scss
index 8701d4225..9d620ee46 100644
--- a/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.scss
+++ b/projects/social_platform/src/app/ui/pages/program/detail/list/rating-card/project-rating/components/range-criterion-input/range-criterion-input.component.scss
@@ -36,27 +36,35 @@
&:focus {
border-color: var(--accent);
- box-shadow: var(--ui-focus-ring);
+
+ @media screen and (max-width: 999px) {
+ box-shadow: var(--ui-focus-ring);
+ }
+
+ @media screen and (min-width: 1000px) {
+ box-shadow: 0 0 6px rgb(109 40 255 / 30%);
+ }
}
}
}
-/* stylelint-disable property-no-vendor-prefix */
input {
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
- -webkit-appearance: none;
+ appearance: none;
}
&[type="number"] {
- -moz-appearance: textfield;
+ appearance: textfield;
}
}
-@include responsive.apply-mobile {
- .field__input {
- width: 44px;
- height: 44px;
- font-size: var(--ui-font-h3);
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .field__input {
+ width: 44px;
+ height: 44px;
+ font-size: var(--ui-font-h3);
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.scss b/projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.scss
index d2b8e90f8..3861bff23 100644
--- a/projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.scss
+++ b/projects/social_platform/src/app/ui/pages/program/detail/main/role-widget/program-role-widget.component.scss
@@ -13,17 +13,22 @@
grid-template-rows: 18px minmax(0, 1fr) 22px;
row-gap: 5px;
width: 100%;
-
- /* Исходная карточка при 100%: 157 × 140.984375 CSS px (Mont, desktop). */
height: 140.9844px;
padding: 7px 8px;
- font-size: var(--ui-font-caption);
line-height: 13px;
color: var(--black);
background: var(--light-white);
border: 0.5px solid var(--medium-grey-for-outline);
border-radius: var(--rounded-lg);
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 10px;
+ }
+
&__header {
display: flex;
gap: 5px;
@@ -87,9 +92,16 @@
&__stage-state {
height: 12px;
margin-top: 3px;
- font-size: var(--ui-font-caption);
line-height: 12px;
color: var(--grey-for-text);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 10px;
+ }
}
&__steps {
@@ -161,9 +173,16 @@
}
dt {
- font-size: var(--ui-font-caption);
line-height: 12px;
color: var(--grey-for-text);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 10px;
+ }
}
dd {
@@ -214,8 +233,15 @@
align-content: center;
min-height: 28px;
margin-top: 6px;
- font-size: var(--ui-font-caption);
line-height: 12px;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 10px;
+ }
}
&__status-label {
@@ -297,34 +323,36 @@
}
}
-@include responsive.apply-below-desktop {
- :host {
- width: 100%;
- min-width: 0;
- }
-
- .widget {
- grid-template-rows: auto minmax(0, 1fr) auto;
- gap: 12px;
- height: auto;
- min-height: 160px;
- padding: 16px;
- font-size: var(--ui-font-body);
- line-height: 1.5;
- }
-
- .widget__footer a,
- .widget__footer button {
- min-height: 44px;
- font-size: var(--ui-font-body);
- }
-
- .widget__ellipsis {
- overflow-wrap: anywhere;
- white-space: normal;
- }
-
- .widget__badge {
- font-size: var(--ui-font-small);
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ :host {
+ width: 100%;
+ min-width: 0;
+ }
+
+ .widget {
+ grid-template-rows: auto minmax(0, 1fr) auto;
+ gap: 12px;
+ height: auto;
+ min-height: 160px;
+ padding: 16px;
+ font-size: var(--ui-font-body);
+ line-height: 1.5;
+ }
+
+ .widget__footer a,
+ .widget__footer button {
+ min-height: 44px;
+ font-size: var(--ui-font-body);
+ }
+
+ .widget__ellipsis {
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
+
+ .widget__badge {
+ font-size: var(--ui-font-small);
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.html b/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.html
index 42654715f..826edca5b 100644
--- a/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.html
+++ b/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.html
@@ -1,44 +1,86 @@
-@if (program()) {
-
-
-
-
-
{{ program().name }}
+@if (desktopLayout()) {
+ @if (program()) {
+
+
-
-
- {{
- registerDateExpired
- ? "регистрация завершена"
- : program().isUserMember
- ? "ты уже участвуешь!"
- : "Регистрация до " + (program().datetimeRegistrationEnds | date: "dd MMMM")
- }}
-
+
+
{{ program().name }}
-
-
- {{ program().datetimeStarted | date: "dd.MM.yyyy" }}
+
+
+ {{
+ registerDateExpired
+ ? "регистрация завершена"
+ : program().isUserMember
+ ? "ты уже участвуешь!"
+ : "Регистрация до " + (program().datetimeRegistrationEnds | date: "dd MMMM")
+ }}
-
-
-
- {{ program().datetimeFinished | date: "dd.MM.yyyy" }}
+
+
+
+ {{ program().datetimeStarted | date: "dd.MM.yyyy" }}
+
+
-
+
+ {{ program().datetimeFinished | date: "dd.MM.yyyy" }}
+
+
+
• для всей России
+
+
+
+ }
+} @else {
+ @if (program()) {
+
+
+
+
+
{{ program().name }}
+
+
+
+ {{
+ registerDateExpired
+ ? "регистрация завершена"
+ : program().isUserMember
+ ? "ты уже участвуешь!"
+ : "Регистрация до " + (program().datetimeRegistrationEnds | date: "dd MMMM")
+ }}
-
-
• для всей России
+
+
+
+ {{ program().datetimeStarted | date: "dd.MM.yyyy" }} -
+ {{ program().datetimeFinished | date: "dd.MM.yyyy" }}
+
+
+
для всей России
+
-
+ }
}
diff --git a/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.scss b/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.scss
index d9bfd33a4..e66ff0477 100644
--- a/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.scss
+++ b/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.scss
@@ -1,77 +1,145 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/responsive";
-.card {
- position: relative;
- display: flex;
- gap: 20px;
- align-items: center;
- max-width: 333px;
+@media screen and (max-width: 999px) {
+ .card {
+ @include ui-foundation.card;
- &__photo {
position: relative;
- z-index: 10;
- flex-shrink: 0;
- width: 123px;
- height: 123px;
- padding: 12px;
- background: var(--white);
- border: 0.5px solid var(--dark-grey);
- border-radius: 50%;
- }
+ display: grid;
+ grid-template-columns: 64px minmax(0, 1fr);
+ gap: 12px;
+ align-items: start;
- &__info {
- @include ui-foundation.card;
+ &__photo {
+ width: 64px;
+ height: 64px;
+ }
- position: relative;
- z-index: 1;
- min-width: 0;
- margin-left: -18%;
- overflow: hidden;
- }
+ &__info {
+ display: grid;
+ gap: 8px;
+ min-width: 0;
+ }
+
+ &__name {
+ /* stylelint-disable-next-line value-no-vendor-prefix */
+ display: -webkit-box;
+ overflow: hidden;
+ font-size: var(--ui-font-body);
+ font-weight: 600;
+ line-height: 20px;
+ color: var(--black);
+ overflow-wrap: anywhere;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+ }
+
+ &__dates {
+ display: grid;
+ gap: 4px;
+ }
+
+ &__description {
+ font-size: var(--ui-font-small);
+ line-height: 18px;
+ color: var(--dark-grey);
+ }
- &__name {
- overflow: hidden;
- color: var(--black);
- text-overflow: ellipsis;
- white-space: nowrap;
+ &__registration {
+ justify-self: start;
+ max-width: 100%;
+ padding: 4px 8px;
+ color: var(--white);
+ overflow-wrap: anywhere;
+ border-radius: var(--rounded-lg);
+
+ &--actual {
+ background-color: var(--accent);
+ }
+
+ &--ended {
+ background-color: var(--red) !important;
+ }
+
+ &--participating {
+ background-color: var(--green);
+ }
+ }
}
+}
- &__dates {
+@media screen and (min-width: 1000px) {
+ .card {
+ position: relative;
display: flex;
- gap: 2px;
- white-space: nowrap;
- }
+ gap: 20px;
+ align-items: center;
+ max-width: 333px;
- &__description {
- color: var(--dark-grey);
- }
+ &__photo {
+ position: relative;
+ z-index: 10;
+ flex-shrink: 0;
+ width: 123px;
+ height: 123px;
+ padding: 12px;
+ background: var(--white);
+ border: 0.5px solid var(--dark-grey);
+ border-radius: 50%;
+ }
+
+ &__info {
+ position: relative;
+ z-index: 1;
+ min-width: 0;
+ padding: 22px;
+ margin-left: -18%;
+ overflow: hidden;
+ border: 0.5px solid var(--dark-grey);
+ border-radius: var(--rounded-lg);
+ }
+
+ &__name {
+ overflow: hidden;
+ color: var(--black);
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
- &__registration {
- padding: 2px 2px 2px 25px;
- margin-top: 2px;
- margin-bottom: 6px;
- overflow: hidden;
- color: var(--white);
- text-overflow: ellipsis;
- white-space: nowrap;
- border-radius: var(--rounded-lg);
-
- &--actual {
- background-color: var(--accent);
+ &__dates {
+ display: flex;
+ gap: 2px;
+ white-space: nowrap;
}
- &--ended {
- background-color: var(--red) !important;
+ &__description {
+ color: var(--dark-grey);
}
- &--participating {
- background-color: var(--green);
+ &__registration {
+ padding: 2px 2px 2px 25px;
+ margin-top: 2px;
+ margin-bottom: 6px;
+ overflow: hidden;
+ color: var(--white);
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ border-radius: var(--rounded-lg);
+
+ &--actual {
+ background-color: var(--accent);
+ }
+
+ &--ended {
+ background-color: var(--red) !important;
+ }
+
+ &--participating {
+ background-color: var(--green);
+ }
}
}
}
diff --git a/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.ts b/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.ts
index a92fc222e..6034b1ab9 100644
--- a/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.ts
+++ b/projects/social_platform/src/app/ui/pages/program/main/program-card/program-card.component.ts
@@ -1,9 +1,12 @@
/** @format */
+import { DesktopLayoutService } from "@uilib";
+/** @format */
+
import { CardDirective } from "@uilib";
/** @format */
-import { ChangeDetectionStrategy, Component, input, Input, OnInit } from "@angular/core";
+import { ChangeDetectionStrategy, Component, inject, input, Input, OnInit } from "@angular/core";
import { AvatarComponent } from "@ui/primitives/avatar/avatar.component";
import { DatePipe, NgClass } from "@angular/common";
import { Program } from "@domain/program/program.model";
@@ -17,6 +20,8 @@ import { Program } from "@domain/program/program.model";
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProgramCardComponent implements OnInit {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
+
readonly program = input.required
();
ngOnInit(): void {
diff --git a/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.html b/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.html
index 12887372a..7b993203c 100644
--- a/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.html
+++ b/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.html
@@ -1,3 +1,31 @@
-
+@if (desktopLayout()) {
+
+} @else {
+
+}
+
+
diff --git a/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.scss b/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.scss
index ce99ec2cc..5fd5a3124 100644
--- a/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.scss
@@ -1,7 +1,66 @@
/** @format */
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
+@use "styles/responsive";
+
+@media screen and (max-width: 999px) {
+ :host {
+ display: block;
+ min-width: 0;
+ max-width: 100%;
+ }
+}
+
+@media screen and (min-width: 1000px) {
+ .bar {
+ display: block;
+ background-color: var(--medium-grey-for-outline);
+ border-radius: var(--rounded-xl);
+
+ &__nav {
+ display: flex;
+ align-items: center;
+ }
+
+ &__tabs {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ padding: 2px;
+ }
+
+ &__item {
+ display: flex;
+ gap: 4px;
+ align-items: center;
+ padding: 5px 30px;
+ color: var(--grey-for-text);
+ cursor: pointer;
+ border-radius: var(--rounded-xl);
+ transition: color 0.2s;
+
+ &:hover {
+ i {
+ color: var(--accent);
+ }
+ }
+ }
+
+ &__link {
+ color: var(--black);
+
+ &--active {
+ .bar__item {
+ background-color: var(--light-white);
+ border: 0.5px solid var(--dark-grey);
+ }
+ }
+
+ &:hover {
+ .bar__item {
+ background-color: var(--white);
+ }
+ }
+ }
+ }
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts b/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts
index 3c89bfda7..dc1c91175 100644
--- a/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts
+++ b/projects/social_platform/src/app/ui/pages/projects/bar-new/bar.component.ts
@@ -1,6 +1,9 @@
/** @format */
-import { ChangeDetectionStrategy, Component, input, Input } from "@angular/core";
+import { DesktopLayoutService } from "@uilib";
+/** @format */
+
+import { inject, ChangeDetectionStrategy, Component, input, Input } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterLink, RouterLinkActive } from "@angular/router";
import { IconComponent, TabsComponent } from "@uilib";
@@ -14,6 +17,8 @@ import { IconComponent, TabsComponent } from "@uilib";
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BarNewComponent {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
+
/** Массив навигационных ссылок */
readonly links = input.required<
{
diff --git a/projects/social_platform/src/app/ui/pages/projects/dashboard/dashboardItem/dashboardItem.component.scss b/projects/social_platform/src/app/ui/pages/projects/dashboard/dashboardItem/dashboardItem.component.scss
index 7ccc0f217..dc829ac00 100644
--- a/projects/social_platform/src/app/ui/pages/projects/dashboard/dashboardItem/dashboardItem.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/dashboard/dashboardItem/dashboardItem.component.scss
@@ -48,10 +48,9 @@
}
}
-@include responsive.apply-mobile {
+@include responsive.apply-below-desktop {
.dashboard__list {
- @include responsive.single-column;
-
+ grid-template-columns: repeat(auto-fill, minmax(0, var(--ui-mobile-entity-card-width)));
row-gap: 48px;
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-left-side/projects-left-side.component.scss b/projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-left-side/projects-left-side.component.scss
index a8f20c411..6d7e055cc 100644
--- a/projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-left-side/projects-left-side.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/detail/info/components/projects-left-side/projects-left-side.component.scss
@@ -1,3 +1,7 @@
+/** @format */
+
+@use "styles/responsive";
+
@mixin expandable-list {
&__remaining {
display: grid;
@@ -68,7 +72,6 @@
align-items: flex-start;
min-width: 0;
- // Длинное имя программы использует всю ширину существующего metadata блока.
&--program {
display: grid;
grid-template-columns: 22px minmax(0, 1fr);
@@ -141,3 +144,23 @@
@include expandable-list;
}
+
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .project__left {
+ width: 100%;
+ }
+
+ .project__section {
+ padding: 16px;
+ }
+
+ .lists__list {
+ gap: 16px;
+ }
+
+ .lists__item {
+ gap: 12px;
+ }
+ }
+}
diff --git a/projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.component.scss b/projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.component.scss
index 0219fccd0..3195861cc 100644
--- a/projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/detail/news-detail/news-detail.component.scss
@@ -6,7 +6,6 @@
display: block;
@include responsive.apply-desktop {
- width: 100%;
- min-width: 0;
+ min-width: 800px;
}
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/detail/team/team.component.scss b/projects/social_platform/src/app/ui/pages/projects/detail/team/team.component.scss
index 75fd64eee..c9b55a441 100644
--- a/projects/social_platform/src/app/ui/pages/projects/detail/team/team.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/detail/team/team.component.scss
@@ -5,17 +5,27 @@
.project {
&__team {
display: grid;
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 156px), 1fr));
- grid-gap: 20px;
align-items: center;
margin-top: 30px;
+
+ @media screen and (max-width: 999px) {
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 156px), 1fr));
+ grid-gap: 20px;
+ }
+
+ @media screen and (min-width: 1000px) {
+ grid-template-columns: repeat(5, 1fr);
+ grid-gap: 20px;
+ }
}
}
-@include responsive.apply-mobile {
- .project__team {
- @include responsive.single-column;
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .project__team {
+ @include responsive.single-column;
- row-gap: 48px;
+ row-gap: 48px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/detail/work-section/work-section.component.scss b/projects/social_platform/src/app/ui/pages/projects/detail/work-section/work-section.component.scss
index 47675d170..129459f98 100644
--- a/projects/social_platform/src/app/ui/pages/projects/detail/work-section/work-section.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/detail/work-section/work-section.component.scss
@@ -39,12 +39,14 @@
}
}
-@include responsive.apply-below-desktop {
- .work-section {
- @include responsive.single-column;
- }
-
- .work-section__section {
- padding: 16px;
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .work-section {
+ @include responsive.single-column;
+ }
+
+ .work-section__section {
+ padding: 16px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.scss b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.scss
index 86075f6a1..520d4d254 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-achievement-step/project-achievement-step.component.scss
@@ -56,8 +56,16 @@
}
&__list {
- width: 100%;
margin-top: 10px;
+
+ @media screen and (max-width: 999px) {
+ width: 100%;
+ }
+
+ @media screen and (min-width: 1000px) {
+ width: 557px;
+ width: 100%;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss
index 1bd624765..fd0e4d5ca 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-additional-step/project-additional-step.component.scss
@@ -166,8 +166,16 @@
}
&__list {
- width: 100%;
margin-top: 10px;
+
+ @media screen and (max-width: 999px) {
+ width: 100%;
+ }
+
+ @media screen and (min-width: 1000px) {
+ width: 557px;
+ width: 100%;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.scss b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.scss
index 15b291323..6627519ac 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-main-step/project-main-step.component.scss
@@ -203,13 +203,21 @@
flex-direction: column;
align-items: center;
justify-content: center;
- width: 100%;
- min-width: 0;
max-width: 100%;
max-height: calc(100vh - 40px);
- padding: 0;
overflow-y: auto;
+ @media screen and (max-width: 999px) {
+ width: 100%;
+ min-width: 0;
+ padding: 0;
+ }
+
+ @media screen and (min-width: 1000px) {
+ width: 700px;
+ padding: 40px 0 80px;
+ }
+
&__cross {
position: absolute;
top: 0;
@@ -271,20 +279,22 @@
}
}
-@include responsive.apply-mobile {
- .project__grid,
- .project__info--additional {
- @include responsive.single-column;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .project__grid,
+ .project__info--additional {
+ @include responsive.single-column;
+ }
- .invite__item {
- flex-wrap: wrap;
- gap: 12px;
- width: 100%;
- min-width: 0;
- }
+ .invite__item {
+ flex-wrap: wrap;
+ gap: 12px;
+ width: 100%;
+ min-width: 0;
+ }
- .invite__item--info {
- min-width: 0;
+ .invite__item--info {
+ min-width: 0;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.html b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.html
index 03bd430e7..713ab43d6 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.html
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.html
@@ -1,8 +1,37 @@
-
+@if (desktopLayout()) {
+
+} @else {
+
+}
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.scss b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.scss
index f11ac252e..182d419dd 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.scss
@@ -1,10 +1,94 @@
/** @format */
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
- padding-block: var(--ui-space-md);
- margin-bottom: var(--ui-space-md);
- border-bottom: 1px solid var(--ui-border-subtle);
+@use "styles/responsive";
+@use "styles/typography";
+
+@media screen and (max-width: 999px) {
+ :host {
+ display: block;
+ min-width: 0;
+ max-width: 100%;
+ padding-block: var(--ui-space-md);
+ margin-bottom: var(--ui-space-md);
+ border-bottom: 1px solid var(--ui-border-subtle);
+ }
+}
+
+@media screen and (min-width: 1000px) {
+ .project {
+ &__navigation {
+ padding: 22px 0;
+ margin-bottom: 22px;
+ border-bottom: 1px solid var(--grey-button);
+ }
+
+ &__nav {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ align-items: center;
+ justify-content: center;
+ padding: 2px 10px;
+ background-color: var(--medium-grey-for-outline);
+ border-radius: var(--rounded-xxl);
+
+ @include responsive.apply-desktop {
+ gap: 0;
+ justify-content: space-between;
+ }
+ }
+
+ &__item {
+ display: flex;
+ gap: 5px;
+ align-items: center;
+ cursor: pointer;
+
+ &--active {
+ padding: 0 8px;
+ margin-right: -8px;
+ margin-left: -8px;
+ background-color: var(--white);
+ border-radius: var(--rounded-xxl);
+ }
+ }
+
+ &__subtitle {
+ color: var(--dark-grey);
+
+ @include typography.body-12;
+
+ &--active {
+ color: var(--black);
+ }
+ }
+
+ &__icon {
+ opacity: 0.1;
+
+ &--active {
+ color: var(--accent);
+ opacity: 1;
+ }
+ }
+
+ &__nav-item {
+ color: var(--dark-grey);
+ cursor: pointer;
+
+ @include typography.heading-4;
+
+ @include responsive.apply-desktop {
+ @include typography.heading-3;
+ }
+
+ &:not(:last-child) {
+ margin-right: 24px;
+ }
+
+ &--active {
+ color: var(--black);
+ }
+ }
+ }
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.ts b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.ts
index b77683c0f..bbe01bc1c 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.ts
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-navigation/project-navigation.component.ts
@@ -12,7 +12,7 @@ import {
output,
} from "@angular/core";
import { ProjectStepService } from "@api/project/project-step.service";
-import { IconComponent, TabsComponent } from "@uilib";
+import { DesktopLayoutService, IconComponent, TabsComponent } from "@uilib";
import { CommonModule } from "@angular/common";
import { Navigation } from "@core/lib/models/navigation.model";
import { EditStep } from "@core/lib/models/edit-step";
@@ -26,6 +26,7 @@ import { EditStep } from "@core/lib/models/edit-step";
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProjectNavigationComponent {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
readonly navItems = input.required();
readonly stepChange = output();
protected readonly tabs = computed(() =>
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.scss b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.scss
index c4dffdf56..92bd6bb77 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-team-step/project-team-step.component.scss
@@ -55,6 +55,12 @@
}
::ng-deep .invite__submit button {
+ @media screen and (min-width: 1000px) {
+ min-height: 25px;
+ padding: 4px 12px;
+ line-height: 16px;
+ }
+
&:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
@@ -139,6 +145,11 @@
}
.team ::ng-deep .invite__submit button {
+ @media screen and (min-width: 1000px) {
+ min-height: 44px;
+ max-height: none;
+ }
+
i {
position: absolute;
left: 12px;
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.scss b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.scss
index 83d16bdc2..2b2a5f909 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/components/project-vacancy-step/project-vacancy-step.component.scss
@@ -114,9 +114,16 @@
&__error {
margin-top: 12px;
- font-size: var(--ui-font-body);
line-height: 20px;
color: var(--black);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ }
}
&__city {
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.html b/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.html
index f544b22d8..86056f6a0 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.html
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.html
@@ -146,7 +146,7 @@ 📢 внимание!
[open]="isSendDescisionLate()"
(openChange)="isSendDescisionLate.set(!isSendDescisionLate())"
>
-
+
Подача проектов завершена!
@@ -159,7 +159,7 @@
📢 внимание!
@defer (when fromProgramOpen()) {
-
+
Начнем создавать историю!
diff --git a/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss b/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss
index 0f1db861c..2dd6d64f4 100644
--- a/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/edit/edit.component.scss
@@ -144,6 +144,12 @@
}
.cancel {
+ @media screen and (min-width: 1000px) {
+ &.cancel--fixed-width {
+ width: 605px;
+ }
+ }
+
display: flex;
flex-direction: column;
align-items: center;
diff --git a/projects/social_platform/src/app/ui/pages/projects/list/list.component.scss b/projects/social_platform/src/app/ui/pages/projects/list/list.component.scss
index 88722d855..5ab519922 100644
--- a/projects/social_platform/src/app/ui/pages/projects/list/list.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/list/list.component.scss
@@ -176,10 +176,9 @@
}
}
-@include responsive.apply-mobile {
+@include responsive.apply-below-desktop {
.page__list {
- @include responsive.single-column;
-
+ grid-template-columns: repeat(auto-fill, minmax(0, var(--ui-mobile-entity-card-width)));
row-gap: 48px;
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/project-activity-card/project-activity-card.component.scss b/projects/social_platform/src/app/ui/pages/projects/project-activity-card/project-activity-card.component.scss
index 1c3e7c1c7..2c03035ef 100644
--- a/projects/social_platform/src/app/ui/pages/projects/project-activity-card/project-activity-card.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/project-activity-card/project-activity-card.component.scss
@@ -1,5 +1,7 @@
/** @format */
+@use "styles/responsive";
+
:host {
display: block;
width: 156px;
@@ -48,10 +50,18 @@
gap: 4px;
align-items: center;
min-width: 0;
- font-size: var(--ui-font-caption);
- font-weight: 400;
line-height: 14px;
color: var(--black);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ font-weight: 400;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 11px;
+ font-weight: 400;
+ }
}
&__icon {
@@ -67,8 +77,6 @@
&__value {
flex: 0 0 auto;
-
- /* Очень большие числа не вытесняют подпись; полное значение остаётся в DOM и title. */
max-width: 45px;
margin: 0 0 0 4px;
overflow: hidden;
@@ -82,3 +90,30 @@
white-space: nowrap;
}
}
+
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ :host {
+ width: 100%;
+ height: auto;
+ }
+
+ .activity {
+ padding: 16px;
+ }
+
+ .activity__title {
+ color: var(--ui-text);
+ }
+
+ .activity__metrics {
+ grid-template-rows: auto;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 12px 16px;
+ }
+
+ .activity__metric + .activity__metric {
+ border-top: 0;
+ }
+ }
+}
diff --git a/projects/social_platform/src/app/ui/pages/projects/projects-activity-placement.spec.ts b/projects/social_platform/src/app/ui/pages/projects/projects-activity-placement.spec.ts
index a2ede1797..eb7c116ea 100644
--- a/projects/social_platform/src/app/ui/pages/projects/projects-activity-placement.spec.ts
+++ b/projects/social_platform/src/app/ui/pages/projects/projects-activity-placement.spec.ts
@@ -2,6 +2,14 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
+import {
+ parseTemplate,
+ TmplAstElement,
+ TmplAstForLoopBlock,
+ TmplAstIfBlock,
+ TmplAstNode,
+ TmplAstTemplate,
+} from "@angular/compiler";
describe("ProjectsComponent: размещение проектной активности", () => {
const template = readFileSync(
@@ -12,17 +20,35 @@ describe("ProjectsComponent: размещение проектной актив
"utf8",
);
+ const activityConditions: string[][] = [];
+ const walk = (nodes: TmplAstNode[], conditions: string[] = []) => {
+ for (const node of nodes) {
+ if (node instanceof TmplAstIfBlock) {
+ for (const branch of node.branches) {
+ walk(branch.children, [...conditions, branch.expression?.source || "else"]);
+ }
+ } else if (node instanceof TmplAstElement || node instanceof TmplAstTemplate) {
+ if (node instanceof TmplAstElement && node.name === "app-project-activity-card") {
+ activityConditions.push(conditions);
+ }
+ walk(node.children, conditions);
+ } else if (node instanceof TmplAstForLoopBlock) {
+ walk(node.children, conditions);
+ }
+ }
+ };
+ walk(parseTemplate(template, "projects.component.html").nodes);
+
it("показывает блок только для dashboard и my", () => {
- expect(template).toMatch(
- /@if \(isMy\(\) \|\| isDashboard\(\)\) \{\s*
{
- const conditionalBlock = new RegExp(
- `@if \\(${condition.replace(/[()]/g, "\\$&")}\\) \\{[\\s\\S]*?
-
- создать проект
-
+ @if (desktopLayout()) {
+
+ } @else {
+
+ создать проект
+
+ }
@@ -60,6 +67,17 @@
+ @if (desktopLayout()) {
+
+ создать проект
+
+
+ }
@if (isDashboard()) {
@@ -80,7 +98,13 @@
}
} @else {
-
+ @if (desktopLayout()) {
+
+ } @else {
+
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/projects.component.scss b/projects/social_platform/src/app/ui/pages/projects/projects.component.scss
index 3bb497f99..48f5563df 100644
--- a/projects/social_platform/src/app/ui/pages/projects/projects.component.scss
+++ b/projects/social_platform/src/app/ui/pages/projects/projects.component.scss
@@ -1,3 +1,5 @@
+/** @format */
+
@use "styles/responsive";
.page {
@@ -32,11 +34,6 @@
display: flex;
flex-direction: column;
align-items: center;
-
- @include responsive.apply-desktop {
- flex: 0 0 var(--ui-compact-sidebar-width);
- width: var(--ui-compact-sidebar-width);
- }
}
&__left {
@@ -85,5 +82,42 @@
}
.bar__add-project {
- margin-bottom: 0;
+ @media screen and (max-width: 999px) {
+ margin-bottom: 0;
+ }
+
+ @media screen and (min-width: 1000px) {
+ margin-bottom: 15px;
+ }
+}
+
+@media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ .page {
+ margin: 24px var(--page-gutter) 0;
+ }
+
+ .page__info {
+ gap: 24px;
+ padding-bottom: 32px;
+ }
+
+ .page__outlet {
+ order: 2;
+ }
+
+ .page__create,
+ .page__left {
+ display: contents;
+ }
+
+ .page__left > app-project-activity-card {
+ order: 1;
+ }
+
+ .page__invites {
+ order: 3;
+ margin-top: 16px;
+ }
+ }
}
diff --git a/projects/social_platform/src/app/ui/pages/projects/projects.component.ts b/projects/social_platform/src/app/ui/pages/projects/projects.component.ts
index fb05448a0..b04dddb2f 100644
--- a/projects/social_platform/src/app/ui/pages/projects/projects.component.ts
+++ b/projects/social_platform/src/app/ui/pages/projects/projects.component.ts
@@ -1,5 +1,8 @@
/** @format */
+import { DesktopLayoutService } from "@uilib";
+/** @format */
+
import {
ChangeDetectionStrategy,
Component,
@@ -48,6 +51,8 @@ import { ProjectActivityCardComponent } from "./project-activity-card/project-ac
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProjectsComponent implements OnInit {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
+
readonly filterBody = viewChild
>("filterBody");
private readonly projectsInfoService = inject(ProjectsInfoService);
diff --git a/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss b/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss
index 03e6e05c6..ec8524c92 100644
--- a/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss
+++ b/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancies-right-side/vacancies-right-side.component.scss
@@ -62,7 +62,14 @@
}
a {
- font-size: var(--ui-font-body);
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ }
+
line-height: 20px;
@include vacancy-ui.link;
diff --git a/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss b/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss
index e2064dedb..1e83f4ce9 100644
--- a/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss
+++ b/projects/social_platform/src/app/ui/pages/vacancies/detail/info/components/vacancy-responses/vacancy-responses.component.scss
@@ -132,18 +132,33 @@
&__label {
margin-bottom: 8px;
- font-size: var(--ui-font-body);
- font-weight: 600;
line-height: 20px;
color: var(--accent-dark);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ font-weight: 600;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ font-weight: 600;
+ }
}
&__file-row {
display: flex;
flex-wrap: wrap;
gap: 6px 10px;
- font-size: var(--ui-font-body);
line-height: 20px;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ }
}
&__file {
diff --git a/projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss b/projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss
index 7ddd5f975..ffc9cb05f 100644
--- a/projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss
+++ b/projects/social_platform/src/app/ui/pages/vacancies/detail/vacancies-detail.component.scss
@@ -60,7 +60,15 @@
&__specialization {
margin-top: 12px;
- font-size: var(--ui-font-body);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ }
+
line-height: 20px;
@include vacancy-ui.secondary;
diff --git a/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.html b/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.html
index 4dd2495fd..2eb39c448 100644
--- a/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.html
+++ b/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.html
@@ -12,28 +12,49 @@
}
@if (hasNoResults()) {
-
- Сбросить фильтры
+ Вакансии не найдены
+ Попробуйте изменить запрос или сбросить фильтры.
+ Сбросить фильтры
+
+ } @else {
+
-
+ Сбросить фильтры
+
+ }
}
}
@if (type() === "my") {
@for (response of responsesList(); track response.id) {
} @empty {
-
- Перейти к вакансиям
+
+ У вас пока нет откликов
+ Найдите подходящую вакансию и расскажите проекту о себе.
+ Перейти к вакансиям
+
+ } @else {
+
-
+ Перейти к вакансиям
+
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.ts b/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.ts
index c7a3b94af..e46219a3d 100644
--- a/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.ts
+++ b/projects/social_platform/src/app/ui/pages/vacancies/list/list.component.ts
@@ -1,6 +1,6 @@
/** @format */
-import { StateComponent } from "@uilib";
+import { DesktopLayoutService, StateComponent } from "@uilib";
/** @format */
// list.component.ts
@@ -35,6 +35,7 @@ import { AppRoutes } from "@api/paths/app-routes";
providers: [VacancyInfoService, VacancyUIInfoService],
})
export class VacanciesListComponent {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
private readonly vacancyInfoService = inject(VacancyInfoService);
private readonly vacancyUIInfoService = inject(VacancyUIInfoService);
diff --git a/projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss b/projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss
index 44ad04fa5..479244524 100644
--- a/projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss
+++ b/projects/social_platform/src/app/ui/pages/vacancies/list/response-card/response-card.component.scss
@@ -42,7 +42,14 @@
}
&__project {
- font-size: var(--ui-font-body);
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ }
+
line-height: 20px;
@include vacancy-ui.link;
@@ -63,10 +70,18 @@
h3 {
margin-bottom: 10px;
- font-size: var(--ui-font-body);
- font-weight: 600;
line-height: 20px;
color: var(--accent-dark);
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ font-weight: 600;
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ font-weight: 600;
+ }
}
}
@@ -76,10 +91,17 @@
gap: 6px 12px;
padding-top: 16px;
margin-top: 16px;
- font-size: var(--ui-font-body);
line-height: 20px;
border-top: 1px solid var(--medium-grey-for-outline);
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-body);
+ }
+
+ @media screen and (min-width: 1000px) {
+ font-size: 13px;
+ }
+
span {
@include vacancy-ui.secondary;
}
diff --git a/projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss b/projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss
index 158add79f..7e14134a4 100644
--- a/projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/autocomplete-input/autocomplete-input.component.scss
@@ -1,217 +1,367 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/responsive";
@use "styles/typography";
-.field {
- position: relative;
- width: 100%;
-
- &__input-wrapper {
- z-index: 3;
- width: 100%;
- overflow: hidden;
- }
-
- &__input {
+@media screen and (max-width: 999px) {
+ .field {
+ position: relative;
width: 100%;
- padding: 12px;
- &::placeholder {
- color: var(--dark-grey);
+ &__input-wrapper {
+ z-index: 3;
+ width: 100%;
+ overflow: hidden;
}
- &--error {
- border-color: var(--red);
+ &__input {
+ width: 100%;
+ padding: 12px;
+
+ &::placeholder {
+ color: var(--dark-grey);
+ }
+
+ &--error {
+ border-color: var(--red);
+ }
+
+ &:focus {
+ border-color: var(--accent);
+ box-shadow: var(--ui-focus-ring);
+ }
+
+ &--no-icon {
+ padding-right: 45px;
+ }
+
+ @include ui-foundation.control;
}
- &:focus {
- border-color: var(--accent);
- box-shadow: var(--ui-focus-ring);
+ &__input-slim {
+ width: 100%;
+ padding: 6px 30px 6px 10px;
+ font-size: var(--ui-font-small);
+ background: transparent;
+ border: none;
+ border-bottom: 1px solid var(--grey-button);
+ outline: none;
+
+ &:focus {
+ border-color: var(--accent);
+
+ + &_arrow {
+ color: var(--accent);
+
+ i {
+ transform: rotate(0);
+ }
+ }
+ }
+
+ @include ui-foundation.control;
}
- &--no-icon {
- padding-right: 45px;
+ &__dropdown {
+ position: relative;
+ right: 0;
+ left: 0;
+ z-index: 4;
+ background-color: transparent;
+ box-shadow: 5px 5px 25px 0 var(--gray);
+ transform-origin: center top;
+
+ &--options,
+ &--no-results {
+ max-height: 300px;
+ max-height: min(300px, calc(var(--visual-viewport-height, 100dvh) - 24px));
+ padding: 10px;
+ overflow-y: auto;
+ overscroll-behavior: contain;
+ background-color: var(--white);
+ scrollbar-width: thin;
+ }
}
- @include ui-foundation.control;
- }
+ &__option {
+ padding: 7px;
+ color: var(--dark-grey);
+ cursor: pointer;
+ border-radius: var(--rounded-lg);
+ transition: background-color 0.2s;
- &__input-slim {
- width: 100%;
- padding: 6px 30px 6px 10px;
- font-size: var(--ui-font-small);
- background: transparent;
- border: none;
- border-bottom: 1px solid var(--grey-button);
- outline: none;
+ &:hover {
+ background-color: var(--light-gray);
+ }
- &:focus {
- border-color: var(--accent);
+ @include typography.body-12;
+
+ &-slim {
+ padding: 3px;
+ }
+ }
- + &_arrow {
- color: var(--accent);
+ &__chip {
+ position: absolute;
+ top: 50%;
+ left: 10px;
+ z-index: 4;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ max-width: 100%;
+ padding: 5px 10px;
+ color: var(--white);
+ background-color: var(--accent);
+ border-radius: var(--rounded-md);
+ transform: translateY(-50%);
+
+ span {
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
- i {
- transform: rotate(0);
- }
+ i {
+ flex-shrink: 0;
+ margin-left: 10px;
+ cursor: pointer;
}
}
- @include ui-foundation.control;
- }
+ &__icons {
+ position: absolute;
+ top: 50%;
+ right: 15px;
+ z-index: 2;
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ opacity: 1;
+ transform: translateY(-50%);
- &__dropdown {
- position: relative;
- right: 0;
- left: 0;
- z-index: 4;
- background-color: transparent;
- box-shadow: 5px 5px 25px 0 var(--gray);
- transform-origin: center top;
-
- &--options,
- &--no-results {
- max-height: 300px;
- max-height: min(300px, calc(var(--visual-viewport-height, 100dvh) - 24px));
- padding: 10px;
- overflow-y: auto;
- overscroll-behavior: contain;
- background-color: var(--white);
- scrollbar-width: thin;
+ &:hover {
+ opacity: 0.6;
+ }
+ }
+
+ &__loading-icon {
+ margin-right: 5px;
}
}
- &__option {
- padding: 7px;
- color: var(--dark-grey);
- cursor: pointer;
- border-radius: var(--rounded-lg);
- transition: background-color 0.2s;
+ :host {
+ display: block;
+ min-width: 0;
+ max-width: 100%;
+ }
+
+ .field,
+ .search,
+ .search__input {
+ min-width: 0;
+ max-width: 100%;
+ }
+
+ @include responsive.apply-mobile {
+ .field__input,
+ .field__input-slim,
+ .search__input input {
+ min-width: 0;
+ max-width: 100%;
+ min-height: 44px;
+ font-size: var(--ui-font-h3);
+ }
- &:hover {
- background-color: var(--light-gray);
+ .field--small,
+ .field__input--small {
+ min-width: 0;
}
- @include typography.body-12;
+ .field__input--with-tooltip {
+ padding-right: 44px;
+ }
- &-slim {
- padding: 3px;
+ .field__option {
+ min-height: 44px;
+ overflow-wrap: anywhere;
}
- }
- &__chip {
- position: absolute;
- top: 50%;
- left: 10px;
- z-index: 4;
- display: flex;
- align-items: center;
- justify-content: center;
- max-width: 100%;
- padding: 5px 10px;
- color: var(--white);
- background-color: var(--accent);
- border-radius: var(--rounded-md);
- transform: translateY(-50%);
-
- span {
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
+ .field__chip {
+ max-width: calc(100% - 44px);
}
- i {
- flex-shrink: 0;
- margin-left: 10px;
- cursor: pointer;
+ .field__chip span {
+ overflow-wrap: anywhere;
+ white-space: normal;
}
- }
- &__icons {
- position: absolute;
- top: 50%;
- right: 15px;
- z-index: 2;
- display: flex;
- align-items: center;
- cursor: pointer;
- opacity: 1;
- transform: translateY(-50%);
+ .field__calendar-button {
+ right: 4px;
+ width: 44px;
+ height: 44px;
+ }
- &:hover {
- opacity: 0.6;
+ .field__input[type="date"] {
+ padding-right: 48px;
}
}
- &__loading-icon {
- margin-right: 5px;
+ .field__input,
+ .field__input-slim {
+ padding-right: 44px;
}
}
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
-}
+@media screen and (min-width: 1000px) {
+ .field {
+ position: relative;
+ width: 100%;
-.field,
-.search,
-.search__input {
- min-width: 0;
- max-width: 100%;
-}
+ &__input-wrapper {
+ z-index: 3;
+ width: 100%;
+ overflow: hidden;
+ }
-@include responsive.apply-mobile {
- .field__input,
- .field__input-slim,
- .search__input input {
- min-width: 0;
- max-width: 100%;
- min-height: 44px;
- font-size: var(--ui-font-h3);
- }
+ &__input {
+ width: 100%;
+ padding: 12px;
+ color: var(--black);
+ background-color: var(--white);
+ border: 0.5px solid var(--gray);
+ border-radius: var(--rounded-xxl);
+ outline: none;
+ transition: all 0.2s;
- .field--small,
- .field__input--small {
- min-width: 0;
- }
+ &::placeholder {
+ color: var(--dark-grey);
+ }
- .field__input--with-tooltip {
- padding-right: 44px;
- }
+ &--error {
+ border-color: var(--red);
+ }
- .field__option {
- min-height: 44px;
- overflow-wrap: anywhere;
- }
+ &:focus {
+ border-color: var(--accent);
+ box-shadow: 0 0 6px rgb(109 40 255 / 30%);
+ }
- .field__chip {
- max-width: calc(100% - 44px);
- }
+ &--no-icon {
+ padding-right: 45px;
+ }
- .field__chip span {
- overflow-wrap: anywhere;
- white-space: normal;
- }
+ @include typography.body-12;
+ }
- .field__calendar-button {
- right: 4px;
- width: 44px;
- height: 44px;
- }
+ &__input-slim {
+ width: 100%;
+ padding: 6px 30px 6px 10px;
+ font-size: 12px;
+ background: transparent;
+ border: none;
+ border-bottom: 1px solid var(--grey-button);
+ outline: none;
- .field__input[type="date"] {
- padding-right: 48px;
- }
-}
+ &:focus {
+ border-color: var(--accent);
-.field__input,
-.field__input-slim {
- padding-right: 44px;
+ +&_arrow {
+ color: var(--accent);
+
+ i {
+ transform: rotate(0);
+ }
+ }
+ }
+ }
+
+ &__dropdown {
+ position: absolute;
+ right: 0;
+ left: 0;
+ z-index: 4;
+ background-color: transparent;
+ box-shadow: 5px 5px 25px 0 var(--gray);
+ transform-origin: center top;
+
+ &--options,
+ &--no-results {
+ scrollbar-width: thin;
+ max-height: 300px;
+ padding: 10px;
+ overflow-y: auto;
+ background-color: var(--white);
+ }
+ }
+
+ &__option {
+ padding: 7px;
+ color: var(--dark-grey);
+ cursor: pointer;
+ border-radius: var(--rounded-lg);
+ transition: background-color 0.2s;
+
+ &:hover {
+ background-color: var(--light-gray);
+ }
+
+ @include typography.body-12;
+
+ &-slim {
+ padding: 3px;
+ }
+ }
+
+ &__chip {
+ position: absolute;
+ top: 50%;
+ left: 10px;
+ z-index: 4;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ max-width: 100%;
+ padding: 5px 10px;
+ color: var(--white);
+ background-color: var(--accent);
+ border-radius: var(--rounded-md);
+ transform: translateY(-50%);
+
+ span {
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ i {
+ flex-shrink: 0;
+ margin-left: 10px;
+ cursor: pointer;
+ }
+ }
+
+ &__icons {
+ position: absolute;
+ top: 50%;
+ right: 15px;
+ z-index: 2;
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ opacity: 1;
+ transform: translateY(-50%);
+
+ &:hover {
+ opacity: 0.6;
+ }
+ }
+
+ &__loading-icon {
+ margin-right: 5px;
+ }
+ }
}
diff --git a/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.html b/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.html
new file mode 100644
index 000000000..803a1e35e
--- /dev/null
+++ b/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.html
@@ -0,0 +1,71 @@
+
+@if (desktopLayout()) {
+
+
+ @if (progress()) {
+
+ }
+
+
![avatar]()
+
+ @if (isOnline()) {
+
+ }
+
+
+} @else {
+
+
+ @if (progress()) {
+
+ }
+
+
![avatar]()
+
+ @if (isOnline()) {
+
+ }
+
+
+}
diff --git a/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.scss b/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.scss
new file mode 100644
index 000000000..9e1c9b40a
--- /dev/null
+++ b/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.scss
@@ -0,0 +1,56 @@
+/** @format */
+@use "../../../../../../ui/src/lib/components/primitives/avatar/avatar.component.scss";
+
+@media screen and (min-width: 1000px) {
+ .avatar {
+ position: relative;
+
+ &__progress {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 3;
+ width: 100%;
+ height: 100%;
+ background:
+ conic-gradient(
+ var(--progress-color) 0 var(--progress),
+ transparent var(--progress) 100%
+ );
+ border-radius: 50%;
+ mask:
+ radial-gradient(
+ circle,
+ transparent calc(50% - var(--progress-width)),
+ white calc(50% - var(--progress-width))
+ );
+ }
+
+ img {
+ position: relative;
+ z-index: 1;
+ border-radius: 50%;
+ object-fit: cover;
+ object-position: center;
+ }
+
+ &__online {
+ position: absolute;
+ right: 0;
+ bottom: -1.5px;
+ z-index: 3;
+ width: 16px;
+ height: 16px;
+ background-color: var(--green);
+ border: 3px solid var(--white);
+ border-radius: 50%;
+ }
+
+ &--border {
+ img {
+ border-style: solid;
+ border-width: 0.5px;
+ }
+ }
+ }
+}
diff --git a/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.ts b/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.ts
index 1e644a4a2..d08067f51 100644
--- a/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.ts
+++ b/projects/social_platform/src/app/ui/primitives/avatar/avatar.component.ts
@@ -1,7 +1,14 @@
-/**
- * Compatibility export. Canonical implementation: @uilib.
- *
- * @format
- */
+/** @format */
+import { ChangeDetectionStrategy, Component, inject } from "@angular/core";
+import { AvatarComponent as CanonicalAvatar, DesktopLayoutService } from "@uilib";
-export { AvatarComponent } from "@uilib";
+/** Legacy desktop presentation with the canonical avatar inputs and mobile view. */
+@Component({
+ selector: "app-avatar",
+ templateUrl: "./avatar.component.html",
+ styleUrl: "./avatar.component.scss",
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class AvatarComponent extends CanonicalAvatar {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
+}
diff --git a/projects/social_platform/src/app/ui/primitives/bar/bar.component.html b/projects/social_platform/src/app/ui/primitives/bar/bar.component.html
index 122ca075e..4a722ae71 100644
--- a/projects/social_platform/src/app/ui/primitives/bar/bar.component.html
+++ b/projects/social_platform/src/app/ui/primitives/bar/bar.component.html
@@ -1,8 +1,46 @@
-
- @if (backHave()) {
-
- }
-
-
+@if (desktopLayout()) {
+
+
+
+} @else {
+
+ @if (backHave()) {
+
+ }
+
+
+}
+
+
diff --git a/projects/social_platform/src/app/ui/primitives/bar/bar.component.scss b/projects/social_platform/src/app/ui/primitives/bar/bar.component.scss
index fb75299fb..0aac735eb 100644
--- a/projects/social_platform/src/app/ui/primitives/bar/bar.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/bar/bar.component.scss
@@ -1,18 +1,123 @@
/** @format */
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
+@use "styles/responsive";
+
+@media screen and (max-width: 999px) {
+ :host {
+ display: block;
+ min-width: 0;
+ max-width: 100%;
+ }
}
.bar {
- display: flex;
- gap: var(--ui-space-sm);
- align-items: center;
- min-width: 0;
+ @media screen and (max-width: 999px) {
+ display: flex;
+ gap: var(--ui-space-sm);
+ align-items: center;
+ min-width: 0;
+ }
+
+ @media screen and (min-width: 1000px) {
+ display: block;
+ height: 63px !important;
+ margin-bottom: 15px;
+ overflow: hidden;
+ background-color: var(--white);
+ border: 1px solid var(--medium-grey-for-outline);
+ border-radius: var(--rounded-xl);
+ }
+
+ @media screen and (min-width: 1000px) {
+ &__nav {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ margin-right: 25px;
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ &__tabs {
+ display: flex;
+
+ li {
+ text-align: center;
+ }
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ &__item {
+ display: flex;
+ align-items: center;
+ padding: 20px 10px;
+ color: var(--dark-grey);
+ cursor: pointer;
+ transition: color 0.2s;
+
+ @include responsive.apply-desktop {
+ padding: 20px;
+ }
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ &__ball {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 22px;
+ min-height: 22px;
+ padding: 1px 6px;
+ margin-left: 6px;
+ line-height: 1;
+ color: var(--white);
+ background-color: var(--gray);
+ border-radius: 7px;
+ transition: background-color 0.2s;
+
+ &--small {
+ padding: 0;
+ border-radius: 100px;
+ }
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ &__link {
+ &--active {
+ .bar__item {
+ color: var(--black);
+ border-bottom: 2px solid var(--black);
+ }
+
+ .bar__ball {
+ background-color: var(--accent);
+ }
+ }
+
+ &:hover {
+ .bar__item {
+ color: var(--black);
+ }
+
+ .bar__ball {
+ background-color: var(--accent);
+ }
+ }
+ }
+ }
+
+ @media screen and (min-width: 1000px) {
+ &__back {
+ margin-top: 45px;
+ }
+ }
}
-app-tabs {
- flex: 1;
+@media screen and (max-width: 999px) {
+ app-tabs {
+ flex: 1;
+ }
}
diff --git a/projects/social_platform/src/app/ui/primitives/bar/bar.component.ts b/projects/social_platform/src/app/ui/primitives/bar/bar.component.ts
index 8bec03119..07f865540 100644
--- a/projects/social_platform/src/app/ui/primitives/bar/bar.component.ts
+++ b/projects/social_platform/src/app/ui/primitives/bar/bar.component.ts
@@ -1,6 +1,9 @@
/** @format */
-import { ChangeDetectionStrategy, Component, input } from "@angular/core";
+import { DesktopLayoutService } from "@uilib";
+/** @format */
+
+import { inject, ChangeDetectionStrategy, Component, input } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterLink, RouterLinkActive } from "@angular/router";
import { BackComponent, TabsComponent } from "@uilib";
@@ -41,6 +44,8 @@ interface BarLinks {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BarComponent {
+ protected readonly desktopLayout = inject(DesktopLayoutService).desktop;
+
/** Массив навигационных ссылок */
links = input.required
();
diff --git a/projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss b/projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss
index e6686a225..6bdcd2551 100644
--- a/projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/checkbox/checkbox.component.scss
@@ -1,13 +1,12 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/responsive";
.field {
- @include ui-foundation.choice;
+ @media screen and (max-width: 999px) {
+ @include ui-foundation.choice;
+ }
position: relative;
display: flex;
@@ -28,29 +27,35 @@
color: var(--light-white);
}
- &:focus-visible {
- outline: 2px solid var(--accent-dark);
- outline-offset: 3px;
+ @media screen and (max-width: 999px) {
+ &:focus-visible {
+ outline: 2px solid var(--accent-dark);
+ outline-offset: 3px;
+ }
}
- &:disabled {
- cursor: not-allowed;
- opacity: var(--ui-disabled-opacity);
+ @media screen and (max-width: 999px) {
+ &:disabled {
+ cursor: not-allowed;
+ opacity: var(--ui-disabled-opacity);
+ }
}
}
-@include responsive.apply-mobile {
- :host {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- min-width: 44px;
- min-height: 44px;
- }
-
- .field::before {
- position: absolute;
- inset: -12px;
- content: "";
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ :host {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 44px;
+ min-height: 44px;
+ }
+
+ .field::before {
+ position: absolute;
+ inset: -12px;
+ content: "";
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/dropdown/dropdown.component.scss b/projects/social_platform/src/app/ui/primitives/dropdown/dropdown.component.scss
index 0030c716b..0664e3524 100644
--- a/projects/social_platform/src/app/ui/primitives/dropdown/dropdown.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/dropdown/dropdown.component.scss
@@ -10,17 +10,27 @@
gap: 5px;
align-items: flex-start;
width: 100%;
- min-width: 0;
- max-width: calc(100vw - 24px);
- max-height: min(300px, calc(var(--visual-viewport-height, 100dvh) - 24px));
- padding: var(--ui-space-sm);
overflow-y: auto;
- overscroll-behavior: contain;
background-color: var(--light-white);
- border: 0.5px solid var(--medium-grey-for-outline);
- border-color: var(--ui-border);
- border-radius: var(--ui-radius-card);
- box-shadow: var(--ui-card-hover-shadow);
+
+ @media screen and (max-width: 999px) {
+ min-width: 0;
+ max-width: calc(100vw - 24px);
+ max-height: min(300px, calc(var(--visual-viewport-height, 100dvh) - 24px));
+ padding: var(--ui-space-sm);
+ overscroll-behavior: contain;
+ border: 0.5px solid var(--medium-grey-for-outline);
+ border-color: var(--ui-border);
+ border-radius: var(--ui-radius-card);
+ box-shadow: var(--ui-card-hover-shadow);
+ }
+
+ @media screen and (min-width: 1000px) {
+ max-height: 200px;
+ padding: 12px;
+ border: 0.5px solid var(--medium-grey-for-outline);
+ border-radius: var(--rounded-lg);
+ }
}
&__option {
@@ -28,14 +38,17 @@
gap: 5px;
align-items: center;
justify-content: space-between;
- width: 100%;
- min-width: 0;
- min-height: var(--ui-control-height);
- padding: 8px 12px;
cursor: pointer;
- border-radius: var(--rounded-lg);
transition: color 0.2s ease-in-out;
+ @media screen and (max-width: 999px) {
+ width: 100%;
+ min-width: 0;
+ min-height: var(--ui-control-height);
+ padding: 8px 12px;
+ border-radius: var(--rounded-lg);
+ }
+
&--add-object {
display: flex;
align-items: center;
@@ -101,13 +114,17 @@
}
}
-.field__option p {
- min-width: 0;
- overflow-wrap: anywhere;
+@media screen and (max-width: 999px) {
+ .field__option p {
+ min-width: 0;
+ overflow-wrap: anywhere;
+ }
}
-@include responsive.apply-mobile {
- .field__option {
- min-height: 44px;
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .field__option {
+ min-height: 44px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/file-item/file-item.component.scss b/projects/social_platform/src/app/ui/primitives/file-item/file-item.component.scss
index 97ef30871..03db598dd 100644
--- a/projects/social_platform/src/app/ui/primitives/file-item/file-item.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/file-item/file-item.component.scss
@@ -2,8 +2,6 @@
@use "styles/responsive";
-/** @format */
-
.file {
display: flex;
gap: 10px;
@@ -23,9 +21,12 @@
&__left {
display: flex;
- flex: 1;
gap: 5px;
align-items: center;
+
+ @media screen and (max-width: 999px) {
+ flex: 1;
+ }
}
&__meta {
@@ -34,7 +35,6 @@
&__icon {
display: flex;
- flex-shrink: 0;
align-items: center;
align-self: center;
justify-content: center;
@@ -44,6 +44,10 @@
border: 0.5px solid var(--medium-grey-for-outline);
border-radius: var(--rounded-xxl);
+ @media screen and (max-width: 999px) {
+ flex-shrink: 0;
+ }
+
&--delete {
color: var(--red);
cursor: pointer;
@@ -61,23 +65,27 @@
}
}
-.file,
-.file__left {
- min-width: 0;
+@media screen and (max-width: 999px) {
+ .file,
+ .file__left {
+ min-width: 0;
+ }
}
-@include responsive.apply-mobile {
- .file {
- flex-wrap: wrap;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .file {
+ flex-wrap: wrap;
+ }
- .file__name {
- overflow-wrap: anywhere;
- white-space: normal;
- }
+ .file__name {
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
- .file__icon {
- width: 44px;
- height: 44px;
+ .file__icon {
+ width: 44px;
+ height: 44px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/input/input.component.scss b/projects/social_platform/src/app/ui/primitives/input/input.component.scss
index 5ff66aaa9..f0ae4a8cf 100644
--- a/projects/social_platform/src/app/ui/primitives/input/input.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/input/input.component.scss
@@ -1,251 +1,442 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/typography";
@use "styles/responsive";
-.field {
- position: relative;
+@media screen and (max-width: 999px) {
+ .field {
+ position: relative;
- &__input {
- &::placeholder {
- color: var(--dark-grey);
- }
+ &__input {
+ &::placeholder {
+ color: var(--dark-grey);
+ }
- &--small {
- max-width: 70px;
- padding: 12px 0;
- text-align: center;
+ &--small {
+ max-width: 70px;
+ padding: 12px 0;
+ text-align: center;
- &--error {
- text-align: start;
+ &--error {
+ text-align: start;
+ }
}
- }
- &--big {
- width: 100%;
- padding: 12px;
- }
+ &--big {
+ width: 100%;
+ padding: 12px;
+ }
- &--with-tooltip {
- padding-right: 60px;
- }
+ &--with-tooltip {
+ padding-right: 60px;
+ }
- &--border {
- border: 0.5px solid var(--gray);
- border-radius: var(--rounded-xxl);
+ &--border {
+ border: 0.5px solid var(--gray);
+ border-radius: var(--rounded-xxl);
- &:focus {
- border-color: var(--accent);
- box-shadow: var(--ui-focus-ring);
+ &:focus {
+ border-color: var(--accent);
+ box-shadow: var(--ui-focus-ring);
+ }
}
- }
- &--error,
- &--overflow {
- border: 0.5px solid var(--red);
+ &--error,
+ &--overflow {
+ border: 0.5px solid var(--red);
- &:focus {
- border-color: var(--red);
- box-shadow: var(--ui-error-ring);
+ &:focus {
+ border-color: var(--red);
+ box-shadow: var(--ui-error-ring);
+ }
}
- }
- @include responsive.apply-desktop {
- @include typography.body-12;
- }
-
- @include ui-foundation.control;
- }
+ @include responsive.apply-desktop {
+ @include typography.body-12;
+ }
- &__input[type="date"]::-webkit-inner-spin-button,
- &__input[type="date"]::-webkit-calendar-picker-indicator {
- display: none;
- appearance: none;
- }
+ @include ui-foundation.control;
+ }
- &__input[type="radio"] {
- position: relative;
- width: 10px;
- height: 10px;
- padding: 4px;
- cursor: pointer;
- border: 0.5px solid var(--dark-grey);
- border-radius: 50%;
- transition:
- border-color 0.2s,
- background-color 0.2s;
- appearance: none;
-
- &:hover::after {
- position: absolute;
- top: 50%;
- left: 50%;
- width: 4px;
- height: 4px;
- content: "";
- background-color: var(--accent);
- border-radius: 50%;
- transform: translate(-50%, -50%);
+ &__input[type="date"]::-webkit-inner-spin-button,
+ &__input[type="date"]::-webkit-calendar-picker-indicator {
+ display: none;
+ appearance: none;
}
- &:checked {
- z-index: 1;
- background-color: var(--accent);
- border-color: var(--accent);
+ &__input[type="radio"] {
+ position: relative;
+ width: 10px;
+ height: 10px;
+ padding: 4px;
+ cursor: pointer;
+ border: 0.5px solid var(--dark-grey);
+ border-radius: 50%;
+ transition:
+ border-color 0.2s,
+ background-color 0.2s;
+ appearance: none;
- &::after {
+ &:hover::after {
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 4px;
content: "";
- background-color: var(--light-gray);
+ background-color: var(--accent);
border-radius: 50%;
transform: translate(-50%, -50%);
}
+
+ &:checked {
+ z-index: 1;
+ background-color: var(--accent);
+ border-color: var(--accent);
+
+ &::after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 4px;
+ height: 4px;
+ content: "";
+ background-color: var(--light-gray);
+ border-radius: 50%;
+ transform: translate(-50%, -50%);
+ }
+ }
+ }
+
+ &__error-icon {
+ position: absolute;
+ top: 50%;
+ right: 26px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--red) !important;
+ pointer-events: none;
+ transform: translateY(-50%);
+
+ &--bare {
+ padding: 0;
+ background: transparent;
+ }
}
- }
- &__error-icon {
- position: absolute;
- top: 50%;
- right: 26px;
- display: flex;
- align-items: center;
- justify-content: center;
- color: var(--red) !important;
- pointer-events: none;
- transform: translateY(-50%);
-
- &--bare {
+ &__right-icon {
+ position: absolute;
+ top: 27%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__calendar-button {
+ position: absolute;
+ top: 50%;
+ right: 18px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
padding: 0;
+ color: var(--accent);
+ cursor: pointer;
background: transparent;
+ border: none;
+ transform: translateY(-50%);
}
- }
- &__right-icon {
- position: absolute;
- top: 27%;
- display: flex;
- align-items: center;
- justify-content: center;
+ &__datepicker-anchor {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ width: 0;
+ height: 0;
+ padding: 0;
+ pointer-events: none;
+ opacity: 0;
+ }
+
+ &__tooltip-wrapper {
+ position: absolute;
+ top: 55%;
+ right: 20px;
+ z-index: 10;
+ padding: 2px;
+ background-color: var(--light-gray);
+ border-radius: 100%;
+ transform: translateY(-50%);
+
+ &--small {
+ top: 15%;
+ right: -3px;
+ }
+ }
+
+ &__counter {
+ position: absolute;
+ right: 18px;
+ bottom: 0;
+
+ p {
+ color: var(--dark-grey);
+ }
+
+ &--overflow {
+ color: var(--red) !important;
+ }
+ }
}
- &__calendar-button {
- position: absolute;
- top: 50%;
- right: 18px;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0;
- color: var(--accent);
- cursor: pointer;
- background: transparent;
- border: none;
- transform: translateY(-50%);
+ :host {
+ display: block;
+ min-width: 0;
+ max-width: 100%;
}
- &__datepicker-anchor {
- position: absolute;
- right: 0;
- bottom: 0;
- width: 0;
- height: 0;
- padding: 0;
- pointer-events: none;
- opacity: 0;
+ .field,
+ .search,
+ .search__input {
+ min-width: 0;
+ max-width: 100%;
}
- &__tooltip-wrapper {
- position: absolute;
- top: 55%;
- right: 20px;
- z-index: 10;
- padding: 2px;
- background-color: var(--light-gray);
- border-radius: 100%;
- transform: translateY(-50%);
+ @include responsive.apply-mobile {
+ .field__input,
+ .field__input-slim,
+ .search__input input {
+ min-width: 0;
+ max-width: 100%;
+ min-height: 44px;
+ font-size: var(--ui-font-h3);
+ }
- &--small {
- top: 15%;
- right: -3px;
+ .field--small,
+ .field__input--small {
+ min-width: 0;
+ }
+
+ .field__input--with-tooltip {
+ padding-right: 44px;
}
- }
- &__counter {
- position: absolute;
- right: 18px;
- bottom: 0;
+ .field__option {
+ min-height: 44px;
+ overflow-wrap: anywhere;
+ }
- p {
- color: var(--dark-grey);
+ .field__chip {
+ max-width: calc(100% - 44px);
}
- &--overflow {
- color: var(--red) !important;
+ .field__chip span {
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
+
+ .field__calendar-button {
+ right: 4px;
+ width: 44px;
+ height: 44px;
+ }
+
+ .field__input[type="date"] {
+ padding-right: 48px;
}
}
}
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
-}
+@media screen and (min-width: 1000px) {
+ .field {
+ position: relative;
-.field,
-.search,
-.search__input {
- min-width: 0;
- max-width: 100%;
-}
+ &__input {
+ color: var(--black) !important;
+ background-color: var(--white);
+ border: none;
+ outline: none;
+ transition: all 0.2s;
-@include responsive.apply-mobile {
- .field__input,
- .field__input-slim,
- .search__input input {
- min-width: 0;
- max-width: 100%;
- min-height: 44px;
- font-size: var(--ui-font-h3);
- }
+ &::placeholder {
+ color: var(--dark-grey);
+ }
- .field--small,
- .field__input--small {
- min-width: 0;
- }
+ &--small {
+ max-width: 70px;
+ padding: 12px 0;
+ text-align: center;
- .field__input--with-tooltip {
- padding-right: 44px;
- }
+ &--error {
+ text-align: start;
+ }
+ }
- .field__option {
- min-height: 44px;
- overflow-wrap: anywhere;
- }
+ &--big {
+ width: 100%;
+ padding: 12px;
+ }
- .field__chip {
- max-width: calc(100% - 44px);
- }
+ &--with-tooltip {
+ padding-right: 60px;
+ }
- .field__chip span {
- overflow-wrap: anywhere;
- white-space: normal;
- }
+ &--border {
+ border: 0.5px solid var(--gray);
+ border-radius: var(--rounded-xxl);
- .field__calendar-button {
- right: 4px;
- width: 44px;
- height: 44px;
- }
+ &:focus {
+ border-color: var(--accent);
+ box-shadow: 0 0 6px rgb(109 40 255 / 30%);
+ }
+ }
+
+ &--error,
+ &--overflow {
+ border: 0.5px solid var(--red);
+
+ &:focus {
+ border-color: var(--red);
+ box-shadow: 0 0 6px rgb(255 40 40 / 30.8%);
+ }
+ }
+
+ @include typography.body-10;
+
+ @include responsive.apply-desktop {
+ @include typography.body-12;
+ }
+ }
+
+ &__input[type="date"]::-webkit-inner-spin-button,
+ &__input[type="date"]::-webkit-calendar-picker-indicator {
+ display: none;
+ appearance: none;
+ }
+
+ &__input[type="radio"] {
+ position: relative;
+ width: 10px;
+ height: 10px;
+ padding: 4px;
+ cursor: pointer;
+ border: 0.5px solid var(--dark-grey);
+ border-radius: 50%;
+ transition: border-color 0.2s, background-color 0.2s;
+ appearance: none;
+
+ &:hover::after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 4px;
+ height: 4px;
+ content: "";
+ background-color: var(--accent);
+ border-radius: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ &:checked {
+ z-index: 1;
+ background-color: var(--accent);
+ border-color: var(--accent);
+
+ &::after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 4px;
+ height: 4px;
+ content: "";
+ background-color: var(--light-gray);
+ border-radius: 50%;
+ transform: translate(-50%, -50%);
+ }
+ }
+ }
+
+ &__error-icon {
+ position: absolute;
+ top: 50%;
+ right: 26px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--red) !important;
+ pointer-events: none;
+ transform: translateY(-50%);
+
+ &--bare {
+ padding: 0;
+ background: transparent;
+ }
+ }
+
+ &__right-icon {
+ position: absolute;
+ top: 27%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__calendar-button {
+ position: absolute;
+ top: 50%;
+ right: 18px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0;
+ color: var(--accent);
+ cursor: pointer;
+ background: transparent;
+ border: none;
+ transform: translateY(-50%);
+ }
+
+ &__datepicker-anchor {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ width: 0;
+ height: 0;
+ padding: 0;
+ pointer-events: none;
+ opacity: 0;
+ }
+
+ &__tooltip-wrapper {
+ position: absolute;
+ top: 55%;
+ right: 20px;
+ z-index: 10;
+ padding: 2px;
+ background-color: var(--light-gray);
+ border-radius: 100%;
+ transform: translateY(-50%);
+
+ &--small {
+ top: 15%;
+ right: -3px;
+ }
+ }
+
+ &__counter {
+ position: absolute;
+ right: 18px;
+ bottom: 0;
- .field__input[type="date"] {
- padding-right: 48px;
+ p {
+ color: var(--dark-grey);
+ }
+
+ &--overflow {
+ color: var(--red) !important;
+ }
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/modal/modal.component.scss b/projects/social_platform/src/app/ui/primitives/modal/modal.component.scss
index cded98e6d..18d997d11 100644
--- a/projects/social_platform/src/app/ui/primitives/modal/modal.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/modal/modal.component.scss
@@ -16,7 +16,14 @@
right: 0;
bottom: 0;
left: 0;
- background-color: var(--ui-backdrop);
+
+ @media screen and (max-width: 999px) {
+ background-color: var(--ui-backdrop);
+ }
+
+ @media screen and (min-width: 1000px) {
+ background-color: rgb(51 46 45 / 50%);
+ }
}
&__body {
@@ -25,18 +32,54 @@
left: 50%;
display: flex;
justify-content: center;
- width: min(var(--ui-dialog-width, var(--ui-dialog-md)), calc(100vw - 24px));
- min-width: 0;
- max-width: calc(100vw - 24px);
- max-height: calc(var(--visual-viewport-height, 100dvh) - 24px);
- padding: var(--ui-dialog-padding);
- overflow-y: auto;
- overscroll-behavior: contain;
+
+ @media screen and (max-width: 999px) {
+ width: min(var(--ui-dialog-width, var(--ui-dialog-md)), calc(100vw - 24px));
+ }
+
+ @media screen and (min-width: 1000px) {
+ width: 90%;
+ }
+
+ @media screen and (max-width: 999px) {
+ min-width: 0;
+ }
+
+ @media screen and (max-width: 999px) {
+ max-width: calc(100vw - 24px);
+ }
+
+ @media screen and (max-width: 999px) {
+ max-height: calc(var(--visual-viewport-height, 100dvh) - 24px);
+ }
+
+ @media screen and (max-width: 999px) {
+ padding: var(--ui-dialog-padding);
+ }
+
+ @media screen and (min-width: 1000px) {
+ padding: 24px;
+ }
+
+ @media screen and (max-width: 999px) {
+ overflow-y: auto;
+ }
+
+ @media screen and (max-width: 999px) {
+ overscroll-behavior: contain;
+ }
+
+ @media screen and (min-width: 1000px) {
+ overflow: hidden;
+ }
+
background: var(--white);
border-radius: var(--ui-radius-dialog);
transform: translate(-50%, -50%);
@include responsive.apply-desktop {
+ width: unset;
+ max-height: 98vh;
overflow-y: auto;
}
@@ -48,66 +91,74 @@
display: block;
}
- ::ng-deep > * {
- flex-shrink: 1;
- min-width: 0;
- max-width: 100%;
- }
-
- @include responsive.apply-below-desktop {
- top: calc(var(--visual-viewport-top, 0px) + var(--visual-viewport-height, 100dvh) / 2);
- padding: var(--ui-dialog-padding);
-
- ::ng-deep .cancel {
+ @media screen and (max-width: 999px) {
+ ::ng-deep > * {
+ flex-shrink: 1;
min-width: 0;
max-width: 100%;
- max-height: none;
- padding: 12px;
}
+ }
- ::ng-deep .cancel__buttons {
- @include responsive.mobile-actions;
+ @media screen and (max-width: 999px) {
+ @include responsive.apply-below-desktop {
+ top: calc(var(--visual-viewport-top, 0px) + var(--visual-viewport-height, 100dvh) / 2);
+ padding: var(--ui-dialog-padding);
- position: sticky;
- bottom: 0;
- z-index: 2;
- justify-content: center;
- padding-top: 8px;
- padding-bottom: env(safe-area-inset-bottom, 0);
- background: var(--white);
- }
+ ::ng-deep .cancel {
+ min-width: 0;
+ max-width: 100%;
+ max-height: none;
+ padding: 12px;
+ }
- ::ng-deep .cancel__text {
- width: 100%;
- }
+ ::ng-deep .cancel__buttons {
+ @include responsive.mobile-actions;
- ::ng-deep .cancel__top {
- position: sticky;
- top: 0;
- z-index: 2;
- background: var(--white);
- }
+ position: sticky;
+ bottom: 0;
+ z-index: 2;
+ justify-content: center;
+ padding-top: 8px;
+ padding-bottom: env(safe-area-inset-bottom, 0);
+ background: var(--white);
+ }
- ::ng-deep .cancel__cross {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- min-width: 44px;
- min-height: 44px;
+ ::ng-deep .cancel__text {
+ width: 100%;
+ }
+
+ ::ng-deep .cancel__top {
+ position: sticky;
+ top: 0;
+ z-index: 2;
+ background: var(--white);
+ }
- svg {
- max-width: 16px;
- max-height: 16px;
+ ::ng-deep .cancel__cross {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 44px;
+ min-height: 44px;
+
+ svg {
+ max-width: 16px;
+ max-height: 16px;
+ }
}
}
}
}
}
-.modal__body--small {
- --ui-dialog-width: var(--ui-dialog-sm);
+@media screen and (max-width: 999px) {
+ .modal__body--small {
+ --ui-dialog-width: var(--ui-dialog-sm);
+ }
}
-.modal__body--large {
- --ui-dialog-width: var(--ui-dialog-lg);
+@media screen and (max-width: 999px) {
+ .modal__body--large {
+ --ui-dialog-width: var(--ui-dialog-lg);
+ }
}
diff --git a/projects/social_platform/src/app/ui/primitives/search/search.component.scss b/projects/social_platform/src/app/ui/primitives/search/search.component.scss
index 5e00182a9..a4416338a 100644
--- a/projects/social_platform/src/app/ui/primitives/search/search.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/search/search.component.scss
@@ -1,112 +1,159 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/responsive";
-.search {
- display: flex;
- align-items: center;
- width: 100%;
- cursor: pointer;
- border-bottom: 0.5px solid var(--dark-grey);
-
- &__other {
- flex-grow: 1;
- }
-
- &__icon {
- margin-right: 4px;
- margin-bottom: 2px;
- color: var(--dark-grey);
+@media screen and (max-width: 999px) {
+ .search {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ cursor: pointer;
+ border-bottom: 0.5px solid var(--dark-grey);
- &--open {
- margin-top: 4px;
- margin-bottom: 0;
+ &__other {
+ flex-grow: 1;
}
- }
- &__text {
- color: var(--dark-grey);
- }
+ &__icon {
+ margin-right: 4px;
+ margin-bottom: 2px;
+ color: var(--dark-grey);
- &__input {
- width: 100%;
+ &--open {
+ margin-top: 4px;
+ margin-bottom: 0;
+ }
+ }
- @include responsive.apply-desktop {
- width: 200px;
+ &__text {
+ color: var(--dark-grey);
}
- input {
+ &__input {
width: 100%;
- background-color: transparent;
- border: none;
- outline: none;
- &::placeholder {
- color: var(--dark-grey);
+ @include responsive.apply-desktop {
+ width: 200px;
}
- @include ui-foundation.control;
- }
- }
-}
+ input {
+ width: 100%;
+ background-color: transparent;
+ border: none;
+ outline: none;
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
-}
+ &::placeholder {
+ color: var(--dark-grey);
+ }
-.field,
-.search,
-.search__input {
- min-width: 0;
- max-width: 100%;
-}
+ @include ui-foundation.control;
+ }
+ }
+ }
-@include responsive.apply-mobile {
- .field__input,
- .field__input-slim,
- .search__input input {
+ :host {
+ display: block;
min-width: 0;
max-width: 100%;
- min-height: 44px;
- font-size: var(--ui-font-h3);
}
- .field--small,
- .field__input--small {
+ .field,
+ .search,
+ .search__input {
min-width: 0;
+ max-width: 100%;
}
- .field__input--with-tooltip {
- padding-right: 44px;
- }
+ @include responsive.apply-mobile {
+ .field__input,
+ .field__input-slim,
+ .search__input input {
+ min-width: 0;
+ max-width: 100%;
+ min-height: 44px;
+ font-size: var(--ui-font-h3);
+ }
- .field__option {
- min-height: 44px;
- overflow-wrap: anywhere;
- }
+ .field--small,
+ .field__input--small {
+ min-width: 0;
+ }
- .field__chip {
- max-width: calc(100% - 44px);
- }
+ .field__input--with-tooltip {
+ padding-right: 44px;
+ }
- .field__chip span {
- overflow-wrap: anywhere;
- white-space: normal;
- }
+ .field__option {
+ min-height: 44px;
+ overflow-wrap: anywhere;
+ }
+
+ .field__chip {
+ max-width: calc(100% - 44px);
+ }
+
+ .field__chip span {
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
+
+ .field__calendar-button {
+ right: 4px;
+ width: 44px;
+ height: 44px;
+ }
- .field__calendar-button {
- right: 4px;
- width: 44px;
- height: 44px;
+ .field__input[type="date"] {
+ padding-right: 48px;
+ }
}
+}
+
+@media screen and (min-width: 1000px) {
+ .search {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ cursor: pointer;
+ border-bottom: 0.5px solid var(--dark-grey);
+
+ &__other {
+ flex-grow: 1;
+ }
- .field__input[type="date"] {
- padding-right: 48px;
+ &__icon {
+ margin-right: 4px;
+ margin-bottom: 2px;
+ color: var(--dark-grey);
+
+ &--open {
+ margin-top: 4px;
+ margin-bottom: 0;
+ }
+ }
+
+ &__text {
+ color: var(--dark-grey);
+ }
+
+ &__input {
+ width: 100%;
+
+ @include responsive.apply-desktop {
+ width: 200px;
+ }
+
+ input {
+ width: 100%;
+ background-color: transparent;
+ border: none;
+ outline: none;
+
+ &::placeholder {
+ color: var(--dark-grey);
+ }
+ }
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/select/select.component.scss b/projects/social_platform/src/app/ui/primitives/select/select.component.scss
index 26758630c..8afe52e48 100644
--- a/projects/social_platform/src/app/ui/primitives/select/select.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/select/select.component.scss
@@ -1,177 +1,284 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/typography";
@use "styles/responsive";
-.field {
- position: relative;
- width: 100%;
-
- &__input {
+@media screen and (max-width: 999px) {
+ .field {
position: relative;
- z-index: 2;
- display: flex;
- align-items: center;
- justify-content: space-between;
- cursor: pointer;
-
- &--small {
- max-width: 70px;
- padding: 12px;
- text-align: center;
+ width: 100%;
+
+ &__input {
+ position: relative;
+ z-index: 2;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ cursor: pointer;
+
+ &--small {
+ max-width: 70px;
+ padding: 12px;
+ text-align: center;
+ }
+
+ &--big {
+ width: 100%;
+ padding: 12px;
+ }
+
+ &--placeholder {
+ color: var(--dark-grey);
+ }
+
+ &--open {
+ border-color: var(--accent);
+ box-shadow: var(--ui-focus-ring);
+ }
+
+ &--error {
+ border-color: var(--red) !important;
+ }
+
+ &--disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+ }
+
+ @include ui-foundation.control;
}
- &--big {
- width: 100%;
- padding: 12px;
+ &__options {
+ position: absolute;
+ right: 0;
+ bottom: -6px;
+ left: 5%;
+ z-index: 11;
+ width: 90%;
+ max-height: 200px;
+ overflow-y: auto;
+ background-color: var(--white);
+ border: 0.5px solid var(--gray);
+ border-radius: var(--rounded-lg);
+ transform: translateY(100%);
}
- &--placeholder {
+ &__option {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 18px;
color: var(--dark-grey);
- }
+ cursor: pointer;
+ border-radius: var(--rounded-lg);
+ transition: background-color 0.2s;
- &--open {
- border-color: var(--accent);
- box-shadow: var(--ui-focus-ring);
- }
+ &--highlighted {
+ background-color: var(--light-gray);
+ }
- &--error {
- border-color: var(--red) !important;
+ &:hover {
+ color: var(--accent);
+ }
}
- &--disabled {
- cursor: not-allowed;
- opacity: 0.5;
+ &__arrow {
+ color: var(--dark-grey);
+ transition: all 0.2s;
+ transform: rotate(180deg);
+
+ &--filpped {
+ color: var(--accent);
+ transform: rotate(0deg);
+ }
}
- @include ui-foundation.control;
+ &__error-icon {
+ flex: 0 0 auto;
+ color: var(--red);
+ pointer-events: none;
+
+ &--bare {
+ padding: 0;
+ background: transparent;
+ }
+ }
}
- &__options {
- position: absolute;
- right: 0;
- bottom: -6px;
- left: 5%;
- z-index: 11;
- width: 90%;
- max-height: 200px;
- overflow-y: auto;
- background-color: var(--white);
- border: 0.5px solid var(--gray);
- border-radius: var(--rounded-lg);
- transform: translateY(100%);
+ :host {
+ display: block;
+ min-width: 0;
+ max-width: 100%;
}
- &__option {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 12px 18px;
- color: var(--dark-grey);
- cursor: pointer;
- border-radius: var(--rounded-lg);
- transition: background-color 0.2s;
+ .field,
+ .search,
+ .search__input {
+ min-width: 0;
+ max-width: 100%;
+ }
- &--highlighted {
- background-color: var(--light-gray);
+ @include responsive.apply-mobile {
+ .field__input,
+ .field__input-slim,
+ .search__input input {
+ min-width: 0;
+ max-width: 100%;
+ min-height: 44px;
+ font-size: var(--ui-font-h3);
}
- &:hover {
- color: var(--accent);
+ .field--small,
+ .field__input--small {
+ min-width: 0;
}
- }
- &__arrow {
- color: var(--dark-grey);
- transition: all 0.2s;
- transform: rotate(180deg);
-
- &--filpped {
- color: var(--accent);
- transform: rotate(0deg);
+ .field__input--with-tooltip {
+ padding-right: 44px;
}
- }
- &__error-icon {
- flex: 0 0 auto;
- color: var(--red);
- pointer-events: none;
+ .field__option {
+ min-height: 44px;
+ overflow-wrap: anywhere;
+ }
- &--bare {
- padding: 0;
- background: transparent;
+ .field__chip {
+ max-width: calc(100% - 44px);
}
- }
-}
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
-}
+ .field__chip span {
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
-.field,
-.search,
-.search__input {
- min-width: 0;
- max-width: 100%;
-}
+ .field__calendar-button {
+ right: 4px;
+ width: 44px;
+ height: 44px;
+ }
-@include responsive.apply-mobile {
- .field__input,
- .field__input-slim,
- .search__input input {
- min-width: 0;
- max-width: 100%;
- min-height: 44px;
- font-size: var(--ui-font-h3);
+ .field__input[type="date"] {
+ padding-right: 48px;
+ }
}
- .field--small,
- .field__input--small {
+ .field__input > span,
+ .field__input > p {
min-width: 0;
+ overflow-wrap: anywhere;
}
- .field__input--with-tooltip {
- padding-right: 44px;
+ .field__arrow,
+ .field__error-icon {
+ flex-shrink: 0;
}
+}
- .field__option {
- min-height: 44px;
- overflow-wrap: anywhere;
- }
+@media screen and (min-width: 1000px) {
+ .field {
+ position: relative;
+ width: 100%;
+
+ &__input {
+ position: relative;
+ z-index: 2;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ color: var(--black);
+ cursor: pointer;
+ background-color: var(--white);
+ border: 0.5px solid var(--gray);
+ border-radius: var(--rounded-xxl);
+ outline: none;
+
+ &--small {
+ max-width: 70px;
+ padding: 12px;
+ text-align: center;
+ }
+
+ &--big {
+ width: 100%;
+ padding: 12px;
+ }
+
+ &--placeholder {
+ color: var(--dark-grey);
+ }
+
+ &--open {
+ border-color: var(--accent);
+ box-shadow: 0 0 6px rgb(109 40 255 / 30%);
+ }
+
+ &--error {
+ border-color: var(--red) !important;
+ }
+
+ &--disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+ }
+
+ @include typography.body-12;
+ }
- .field__chip {
- max-width: calc(100% - 44px);
- }
+ &__options {
+ position: absolute;
+ right: 0;
+ bottom: -6px;
+ left: 5%;
+ z-index: 11;
+ width: 90%;
+ max-height: 200px;
+ overflow-y: auto;
+ background-color: var(--white);
+ border: 0.5px solid var(--gray);
+ border-radius: var(--rounded-lg);
+ transform: translateY(100%);
+ }
- .field__chip span {
- overflow-wrap: anywhere;
- white-space: normal;
- }
+ &__option {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 18px;
+ color: var(--dark-grey);
+ cursor: pointer;
+ border-radius: var(--rounded-lg);
+ transition: background-color 0.2s;
- .field__calendar-button {
- right: 4px;
- width: 44px;
- height: 44px;
- }
+ &--highlighted {
+ background-color: var(--light-gray);
+ }
- .field__input[type="date"] {
- padding-right: 48px;
- }
-}
+ &:hover {
+ color: var(--accent);
+ }
+ }
-.field__input > span,
-.field__input > p {
- min-width: 0;
- overflow-wrap: anywhere;
-}
+ &__arrow {
+ color: var(--dark-grey);
+ transition: all 0.2s;
+ transform: rotate(180deg);
+
+ &--filpped {
+ color: var(--accent);
+ transform: rotate(0deg);
+ }
+ }
-.field__arrow,
-.field__error-icon {
- flex-shrink: 0;
+ &__error-icon {
+ flex: 0 0 auto;
+ color: var(--red);
+ pointer-events: none;
+
+ &--bare {
+ padding: 0;
+ background: transparent;
+ }
+ }
+ }
}
diff --git a/projects/social_platform/src/app/ui/primitives/switch/switch.component.scss b/projects/social_platform/src/app/ui/primitives/switch/switch.component.scss
index ff0112559..b589397ea 100644
--- a/projects/social_platform/src/app/ui/primitives/switch/switch.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/switch/switch.component.scss
@@ -31,18 +31,20 @@
}
}
-@include responsive.apply-mobile {
- :host {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- min-width: 44px;
- min-height: 44px;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ :host {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 44px;
+ min-height: 44px;
+ }
- .switch::before {
- position: absolute;
- inset: -12px -2px;
- content: "";
+ .switch::before {
+ position: absolute;
+ inset: -12px -2px;
+ content: "";
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/tag/tag.component.scss b/projects/social_platform/src/app/ui/primitives/tag/tag.component.scss
index 14d8f9629..b0190ed62 100644
--- a/projects/social_platform/src/app/ui/primitives/tag/tag.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/tag/tag.component.scss
@@ -1,15 +1,12 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/responsive";
-/** @format */
-
.tag {
- @include ui-foundation.badge;
+ @media screen and (max-width: 999px) {
+ @include ui-foundation.badge;
+ }
position: relative;
display: flex;
@@ -17,10 +14,25 @@
justify-content: center;
width: 100%;
max-width: 120px;
- padding: 4px 12px;
+
+ @media screen and (max-width: 999px) {
+ padding: 4px 12px;
+ }
+
+ @media screen and (min-width: 1000px) {
+ padding: 2px 20px;
+ }
+
overflow: hidden;
- font-size: var(--ui-font-caption);
- line-height: 1.5;
+
+ @media screen and (max-width: 999px) {
+ font-size: var(--ui-font-caption);
+ }
+
+ @media screen and (max-width: 999px) {
+ line-height: 1.5;
+ }
+
color: var(--accent);
text-overflow: ellipsis;
white-space: nowrap;
@@ -192,25 +204,27 @@
}
}
-@include responsive.apply-mobile {
- .tag {
- max-width: 100%;
- padding: 4px 12px;
- overflow-wrap: anywhere;
- white-space: normal;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .tag {
+ max-width: 100%;
+ padding: 4px 12px;
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
- .tag p {
- min-width: 0;
- }
+ .tag p {
+ min-width: 0;
+ }
- .tag:has(.tag__icons) {
- padding-right: 40px;
- }
+ .tag:has(.tag__icons) {
+ padding-right: 40px;
+ }
- .tag__icons {
- top: 0;
- bottom: 0;
- align-items: center;
+ .tag__icons {
+ top: 0;
+ bottom: 0;
+ align-items: center;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss b/projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss
index 6c32da48c..3003879cf 100644
--- a/projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/textarea/textarea.component.scss
@@ -1,33 +1,12 @@
/** @format */
@use "styles/ui-foundation";
-
-/** @format */
-
@use "styles/typography";
@use "styles/responsive";
-.field {
- position: relative;
-
- &--small {
- min-width: 245px;
- }
-
- &--big {
- width: 100%;
- }
-
- &__input {
- display: block;
- width: 100%;
- min-height: 162px;
- padding: 12px 18px;
- resize: none;
-
- &::placeholder {
- color: var(--dark-grey);
- }
+@media screen and (max-width: 999px) {
+ .field {
+ position: relative;
&--small {
min-width: 245px;
@@ -37,131 +16,256 @@
width: 100%;
}
- &--with-tooltip {
- padding-right: 130px;
- padding-right: 60px;
- }
+ &__input {
+ display: block;
+ width: 100%;
+ min-height: 162px;
+ padding: 12px 18px;
+ resize: none;
- &--error,
- &--overflow {
- border: 0.5px solid var(--red);
+ &::placeholder {
+ color: var(--dark-grey);
+ }
+
+ &--small {
+ min-width: 245px;
+ }
+
+ &--big {
+ width: 100%;
+ }
+
+ &--with-tooltip {
+ padding-right: 130px;
+ padding-right: 60px;
+ }
+
+ &--error,
+ &--overflow {
+ border: 0.5px solid var(--red);
+
+ &:focus {
+ border-color: var(--red) !important;
+ box-shadow: var(--ui-error-ring) !important;
+ }
+ }
&:focus {
- border-color: var(--red) !important;
- box-shadow: var(--ui-error-ring) !important;
+ border-color: var(--accent);
+ box-shadow: var(--ui-focus-ring);
}
- }
- &:focus {
- border-color: var(--accent);
- box-shadow: var(--ui-focus-ring);
+ @include ui-foundation.control;
+
+ border-radius: var(--ui-radius-card);
}
- @include ui-foundation.control;
+ &__error-icon {
+ position: absolute;
+ top: 25px;
+ right: 15px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--red) !important;
+ pointer-events: none;
+ transform: translateY(-50%);
- border-radius: var(--ui-radius-card);
- }
+ i {
+ color: var(--red) !important;
+ }
- &__error-icon {
- position: absolute;
- top: 25px;
- right: 15px;
- display: flex;
- align-items: center;
- justify-content: center;
- color: var(--red) !important;
- pointer-events: none;
- transform: translateY(-50%);
-
- i {
- color: var(--red) !important;
+ &--bare {
+ padding: 0;
+ background: transparent;
+ }
+ }
+
+ &__tooltip-wrapper {
+ position: absolute;
+ top: 25px;
+ right: 15px;
+ z-index: 10;
+ padding: 2px;
+ background-color: var(--light-gray);
+ border-radius: 100%;
+ transform: translateY(-50%);
}
- &--bare {
- padding: 0;
- background: transparent;
+ &__counter {
+ position: absolute;
+ right: 18px;
+ bottom: 4px;
+
+ p {
+ color: var(--dark-grey);
+ }
+
+ &--overflow {
+ color: var(--red) !important;
+ }
}
}
- &__tooltip-wrapper {
- position: absolute;
- top: 25px;
- right: 15px;
- z-index: 10;
- padding: 2px;
- background-color: var(--light-gray);
- border-radius: 100%;
- transform: translateY(-50%);
+ :host {
+ display: block;
+ min-width: 0;
+ max-width: 100%;
+ }
+
+ .field,
+ .search,
+ .search__input {
+ min-width: 0;
+ max-width: 100%;
}
- &__counter {
- position: absolute;
- right: 18px;
- bottom: 4px;
+ @include responsive.apply-mobile {
+ .field__input,
+ .field__input-slim,
+ .search__input input {
+ min-width: 0;
+ max-width: 100%;
+ min-height: 44px;
+ font-size: var(--ui-font-h3);
+ }
- p {
- color: var(--dark-grey);
+ .field--small,
+ .field__input--small {
+ min-width: 0;
}
- &--overflow {
- color: var(--red) !important;
+ .field__input--with-tooltip {
+ padding-right: 44px;
+ }
+
+ .field__option {
+ min-height: 44px;
+ overflow-wrap: anywhere;
+ }
+
+ .field__chip {
+ max-width: calc(100% - 44px);
+ }
+
+ .field__chip span {
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
+
+ .field__calendar-button {
+ right: 4px;
+ width: 44px;
+ height: 44px;
+ }
+
+ .field__input[type="date"] {
+ padding-right: 48px;
}
}
}
-:host {
- display: block;
- min-width: 0;
- max-width: 100%;
-}
+@media screen and (min-width: 1000px) {
+ .field {
+ position: relative;
-.field,
-.search,
-.search__input {
- min-width: 0;
- max-width: 100%;
-}
+ &--small {
+ min-width: 245px;
+ }
-@include responsive.apply-mobile {
- .field__input,
- .field__input-slim,
- .search__input input {
- min-width: 0;
- max-width: 100%;
- min-height: 44px;
- font-size: var(--ui-font-h3);
- }
+ &--big {
+ width: 100%;
+ }
- .field--small,
- .field__input--small {
- min-width: 0;
- }
+ &__input {
+ display: block;
+ width: 100%;
+ min-height: 162px;
+ padding: 12px 18px;
+ color: var(--black);
+ resize: none;
+ background-color: var(--white);
+ border: 0.5px solid var(--gray);
+ border-radius: var(--rounded-xl);
+ outline: none;
+ transition: all 0.2s;
+
+ &::placeholder {
+ color: var(--dark-grey);
+ }
- .field__input--with-tooltip {
- padding-right: 44px;
- }
+ &--small {
+ min-width: 245px;
+ }
- .field__option {
- min-height: 44px;
- overflow-wrap: anywhere;
- }
+ &--big {
+ width: 100%;
+ }
- .field__chip {
- max-width: calc(100% - 44px);
- }
+ &--with-tooltip {
+ padding-right: 130px;
+ }
- .field__chip span {
- overflow-wrap: anywhere;
- white-space: normal;
- }
+ &--error,
+ &--overflow {
+ border: 0.5px solid var(--red);
- .field__calendar-button {
- right: 4px;
- width: 44px;
- height: 44px;
- }
+ &:focus {
+ border-color: var(--red) !important;
+ box-shadow: 0 0 6px rgb(255 40 40 / 30.8%) !important;
+ }
+ }
+
+ &:focus {
+ border-color: var(--accent);
+ box-shadow: 0 0 6px rgb(109 40 255 / 30%);
+ }
+ }
+
+ &__error-icon {
+ position: absolute;
+ top: 25px;
+ right: 15px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--red) !important;
+ pointer-events: none;
+ transform: translateY(-50%);
- .field__input[type="date"] {
- padding-right: 48px;
+ i {
+ color: var(--red) !important;
+ }
+
+ &--bare {
+ padding: 0;
+ background: transparent;
+ }
+ }
+
+ &__tooltip-wrapper {
+ position: absolute;
+ top: 25px;
+ right: 15px;
+ z-index: 10;
+ padding: 2px;
+ background-color: var(--light-gray);
+ border-radius: 100%;
+ transform: translateY(-50%);
+ }
+
+ &__counter {
+ position: absolute;
+ right: 18px;
+ bottom: 4px;
+
+ p {
+ color: var(--dark-grey);
+ }
+
+ &--overflow {
+ color: var(--red) !important;
+ }
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.scss b/projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.scss
index fc2230911..a71af676a 100644
--- a/projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.scss
+++ b/projects/social_platform/src/app/ui/primitives/upload-file/upload-file.component.scss
@@ -56,7 +56,6 @@
border-radius: var(--rounded-lg);
&__title {
- /* width: 80%; */
overflow: hidden;
color: var(--black);
text-overflow: ellipsis;
@@ -88,34 +87,36 @@
}
}
-@include responsive.apply-mobile {
- .control {
- height: auto;
- min-height: 120px;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .control {
+ height: auto;
+ min-height: 120px;
+ }
- .control label {
- min-height: 120px;
- padding: 16px;
- }
+ .control label {
+ min-height: 120px;
+ padding: 16px;
+ }
- .control__success,
- .file {
- flex-wrap: wrap;
- min-width: 0;
- max-width: 100%;
- }
+ .control__success,
+ .file {
+ flex-wrap: wrap;
+ min-width: 0;
+ max-width: 100%;
+ }
- .file__title {
- min-width: 0;
- max-width: 100%;
- overflow-wrap: anywhere;
- white-space: normal;
- }
+ .file__title {
+ min-width: 0;
+ max-width: 100%;
+ overflow-wrap: anywhere;
+ white-space: normal;
+ }
- .file__basket,
- .file__replace {
- min-width: 44px;
- min-height: 44px;
+ .file__basket,
+ .file__replace {
+ min-width: 44px;
+ min-height: 44px;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/widgets/cookie-consent/cookie-consent.component.scss b/projects/social_platform/src/app/ui/widgets/cookie-consent/cookie-consent.component.scss
index de7c55c2d..e9302095a 100644
--- a/projects/social_platform/src/app/ui/widgets/cookie-consent/cookie-consent.component.scss
+++ b/projects/social_platform/src/app/ui/widgets/cookie-consent/cookie-consent.component.scss
@@ -2,8 +2,6 @@
@use "styles/responsive";
-/** @format */
-
.cookie-consent {
position: fixed;
right: 20px;
@@ -38,18 +36,20 @@
}
}
-@include responsive.apply-mobile {
- .cookie-consent {
- right: var(--page-gutter);
- bottom: max(12px, env(safe-area-inset-bottom));
- left: var(--page-gutter);
- max-width: none;
- max-height: calc(100dvh - 24px);
- padding: 16px;
- overflow-y: auto;
- }
+@media screen and (max-width: 999px) {
+ @include responsive.apply-mobile {
+ .cookie-consent {
+ right: var(--page-gutter);
+ bottom: max(12px, env(safe-area-inset-bottom));
+ left: var(--page-gutter);
+ max-width: none;
+ max-height: calc(100dvh - 24px);
+ padding: 16px;
+ overflow-y: auto;
+ }
- .cookie-consent__buttons {
- @include responsive.mobile-actions;
+ .cookie-consent__buttons {
+ @include responsive.mobile-actions;
+ }
}
}
diff --git a/projects/social_platform/src/app/ui/widgets/detail/detail.component.html b/projects/social_platform/src/app/ui/widgets/detail/detail.component.html
index 8b90c4323..703713ece 100644
--- a/projects/social_platform/src/app/ui/widgets/detail/detail.component.html
+++ b/projects/social_platform/src/app/ui/widgets/detail/detail.component.html
@@ -5,20 +5,16 @@
@if (info()) {
- @if (appWidth > 1000) {
-
![cover]()
- }
-
-
+
- @if (listType() === "project") {
+ @if (appWidth >= 1000 && (listType() === "project" || listType() === "profile")) {