Список всех рабочих прототипов по задачам — чтобы не искать пути к файлам вручную. У каждого прототипа в шапке кликабельно лого — открывает требования по задаче.
Клик «В корзину» на карточке товара (моб.) не даёт пользователю подтверждения добавления.
Момент сразу после решения о покупке не используется для допродажи услуг.
После клика «В корзину» на мобильной версии сайта открывается модальное окно:
Допродажа не должна конкурировать с переходом в корзину за главное действие.
Событие добавления услуги из этого окна.
Окно открывается по клику на «В корзину» в блоке покупки карточки товара.
Подтверждение — всегда. Карточки услуг — всегда, независимо от того, добавлена услуга или нет. Если подходящих услуг нет — блока допродажи нет, окно состоит из подтверждения и двух CTA.
Для каждой услуги: заголовок, 2–3 преимущества, цена, флажок-переключатель — тот же компонент, что и на карточке товара. Рейтинг/отзывы не показываются. Флажок по умолчанию снят. Блок скроллится внутри окна.
Включение флажка добавляет услугу, выключение — удаляет. Отдельной кнопки подтверждения нет. Услуги не исключают друг друга — можно включить обе. Переключатели в модалке и виджеты на карточке товара — общее состояние: изменение в одном месте отражается в другом.
«Перейти в корзину» — залитая кнопка, закреплена внизу окна, не скроллится. Скроллится только контент выше футера.
ook-839-product-card-mobile-tobe.html — новый экран, у задачи нет as-is.
Внутренний журнал изменений по датам — не для дизайнера/аналитика, но полезен при дальнейших доработках. Актуальные требования — в соседнем документе «Требования к задаче».
Задача поставлена коротко: добавить на мобильной версии сайта модальное окно после добавления товара в корзину, сохранив главный CTA перехода в корзину и добавив туда оффер услуги, которую нужно реально «продать» — с преимуществами, а не сухим переключателем.
Прежде чем строить прототип, обнаружена и исправлена нестыковка данных, унаследованная из более ранних раундов OOK-836. Карточка товара (ook-836-product-card-tobe.html/-mobile-tobe.html) с самого начала показывает реальный товар Indesit ITS 5200 NG Темно-серый (сверено с живым сайтом ещё в рамках as-is), а корзина/чекаут под тем же id fridge — Haier BCF5261WRU по цене 96 999 ₽, унаследованный ещё из демо-данных OOK-696 и никогда не сверенный с карточкой товара. Пока привязка услуги к товару была решена на уровне абстрактной категории, это расхождение было незаметно; с появлением реальной привязки к конкретному товару (доработка 10 задачи OOK-836) оно стало бы видно сразу — а новое модальное окно OOK-839 сделало бы его видимым немедленно и наглядно (пользователь видит «Indesit» на кнопке «В корзину», а в корзине — «Haier»). Исправлено во всех местах: ook-836-cart-tobe.html/-mobile-tobe.html, ook-836-checkout-tobe.html/-mobile-tobe.html (ITEM_CATALOG), ook-836-service-card-tobe.html/-mobile-tobe.html (подпись привязки) — название, цена (41 579 ₽), бонус (+415) и строка рассрочки товара с id fridge приведены к тем же значениям, что уже на карточке товара; суммы корзины/чекаута пересчитаны.
Прототип ook-839-product-card-mobile-tobe.html — построен поверх карточки товара OOK-836, без изменений там, кроме одного: кнопка «В корзину» в блоке покупки (была декоративной) теперь открывает модальное окно. Окно состоит из: подтверждения добавления (миниатюра/название/цена), блока допродажи услуги (заголовок-оффер «Доверьте установку профессионалам», 3 преимущества с иконками, рейтинг 4.9 · 8 отзывов, цена, кнопка «Добавить» в один тап) или компактной отметки «Установка уже в корзине», если услуга уже добавлена, и снизу — всегда видимого главного CTA «Перейти в корзину →» и вторичного «Продолжить покупки».
Добавление услуги из окна реально работает, не имитация: переиспользован контракт localStorage['ook836ServiceState'], уже созданный в OOK-836 для тумблера на карточке товара — привязка к тому же товару (linkedItemId: 'fridge'), только со своим значением addedVia: 'modal' для различения источника добавления в аналитике. При добавлении из окна тумблер виджета на этой же странице сразу отражает новое состояние (общий источник истины), а при переходе в корзину услуга корректно показывается вложенной в карточку товара — та же логика каскадного отображения, что уже была построена для виджета.
Найден и исправлен реальный CSS-баг того же типа, что уже несколько раз фиксировался в проекте (класс с безусловным display: flex перебивает браузерное правило [hidden]{display:none}): блок «уже в корзине» был виден одновременно с блоком-оффером услуги, хотя JS корректно выставлял атрибут hidden — обнаружено визуально на скриншоте, не по логам (JS-проверка самого атрибута hidden ничего не показывала, т.к. атрибут действительно стоял верно — проблема была именно в CSS-специфичности, а не в логике). Исправлено добавлением явных [hidden]{display:none}-переопределений для обоих блоков.
Проверено через Playwright: клик «В корзину» → окно открывается с оффером услуги (услуги ещё нет) → клик «Добавить» → оффер сменяется отметкой «уже в корзине», тумблер виджета на странице обновляется синхронно → переход в корзину → услуга корректно показана вложенной в карточку Indesit ITS 5200 NG, суммы верны (44 091 ₽) — без ошибок в консоли.
Правки по прямому запросу: (1) добавить в окно обе услуги — установку и гарантию; (2) добавление услуги — радиобаттонами; (3) кнопка «Перейти в корзину» не должна скроллиться вместе с контентом допродажи.
Вторая услуга — «Гарантия Премиум, 3 года», 8 730 ₽ (цифра взята из уже существующего на этой же странице декоративного виджета гарантии — единственный реальный референс цены в прототипе). Новый демо-артикул ГАР-ПРЕМ-3Y, до этого гарантия нигде в прототипах не была настоящим добавляемым в корзину товаром (только невживлённый тумблер). Блок допродажи в окне переведён с одной кнопки «Добавить» на пару радиокарточек (заголовок, преимущества, рейтинг, цена у каждой) плюс общая кнопка «Добавить услугу», активная только когда выбран один из вариантов — выбор взаимоисключающий сознательно, а не только по форме радиобаттонов: общее состояние ook836ServiceState, унаследованное из OOK-836, хранит ровно одну активную услугу, поэтому реально одновременно добавить обе через это окно и так было бы нельзя — ограничение архитектуры, а не искусственное сужение UI. Задокументировано как открытый вопрос в требованиях.
Закреплённый CTA: базовый компонент .modal-box скроллит целиком, включая футер — переопределено для этого окна: сам бокс стал flex-колонкой с overflow:hidden, контент (подтверждение + блок допродажи) вынесен в отдельный скроллящийся .ook839-modal-scroll, а футер с CTA — невскроллящийся flex-элемент с верхней границей, всегда виден.
Правки в соседних файлах, без которых вторая услуга работала бы нечестно: вложенный блок услуги в корзине (ook-836-cart-mobile-tobe.html) раньше был статичной вёрсткой с захардкоженным текстом «Установка встроенного холодильника» и проверкой state.itemId === 'install-haier' — если бы через это окно добавили гарантию, блок остался бы скрыт (услуга «пропадала» бы из корзины) либо показывал неверный текст. Переписано на заполнение title/артикула/цены из самого state и проверку по факту наличия состояния, а не по конкретному id услуги; текст каскадного тоста при удалении товара также стал общим («{название услуги} для «{товар}» удалена вместе с товаром» вместо захардкоженного «Установка для…»). В чекауте (ook-836-checkout-mobile-tobe.html) добавлена вторая запись в ITEM_CATALOG для warranty-premium — без неё чекаут молча игнорировал бы эту позицию, не выдавая ошибки, но и не показывая её (тот же паттерн блока seller:'services', что и у установки, обязательная предоплата онлайн работает автоматически). Десктопные версии cart/checkout и отдельная карточка услуги не тронуты — вторая услуга добавляется только через это мобильное окно, десктоп и карточка услуги остаются только про установку, вне скоупа OOK-839.
Пять точечных правок по прямому запросу, все — в пределах одного файла ook-839-product-card-mobile-tobe.html: (1) кнопка «Перейти в корзину» перестала переходить в прототип OOK-836 — просто ничего не делает по клику; (2) выбор услуг переведён с радиобаттонов на тот же флажок/слайдер, что у виджета на карточке товара (переиспользованы классы .m-addon-widget-toggle/.knob — тот же компонент один в один, не копия); (3) флажки услуг сняты по умолчанию — и на виджете карточки товара, и в модалке; (4) кнопка «Добавить услугу» и отдельное состояние окна «услуга уже в корзине» убраны — включённый флажок и есть добавление, выключенный — удаление, без промежуточных состояний; (5) рейтинг и отзывы убраны у обеих карточек услуг в модалке — у этих услуг их пока нет.
Взаимоисключение услуг сохранено, но перенесено с уровня контрола (радио) на уровень логики (JS): общее состояние ook836ServiceState по-прежнему хранит только одну активную услугу (архитектура OOK-836, не пересматривалась в этом раунде) — при включении флажка одной услуги обработчик читает состояние заново и снимает флажок другой, если он был включён; визуально это два независимых переключателя, поведенчески — честное отражение того, что реально может лежать в общем слоте состояния. То же самое автоматически синхронизирует тумблер «Установка» на самой странице карточки товара в обе стороны.
Дефолт снят — убрано сидирование демо-состояния: функция seedServiceStateIfNeeded() (унаследованная из OOK-836, подсаживала «Установка уже в корзине» при первом визите) удалена из этого файла вместе с вызовом — при пустом хранилище оба флажка в модалке и тумблер виджета показывают выключенное состояние. Убрано только в этом файле; собственные файлы OOK-836 (карточка товара, корзина, чекаут, карточка услуги) не тронуты и сидирование там не убиралось — не входило в запрос этого раунда.
Проверено через Playwright: очистка хранилища → и виджет, и оба флажка в модалке выключены → включение «Установка» пишет состояние и сразу синхронизирует тумблер на странице → включение «Гарантия» автоматически гасит «Установка» в модалке и на странице, пишет новое состояние → выключение активного флажка полностью очищает состояние → клик «Перейти в корзину» не меняет location.href — без ошибок в консоли (кроме не относящегося к делу 404 на favicon.ico).
Две правки по прямому запросу: (1) услуги должны быть выбираемы одновременно, а не одна вместо другой; (2) виджеты «Установка»/«Гарантия» на карточке товара и переключатели в модалке — одни и те же услуги, с наследованием «выбранности» в обе стороны.
Второй пункт оказался предпосылкой первого: до этой доработки второй виджет на странице («Гарантия», .m-addon-widget с тумблером «72 часа…») был чисто декоративным — тумблер ничего не писал в состояние, только визуально переключался. Подключен к тому же общему состоянию, что и «Установка»: добавлен id="m-warranty-toggle" и обработчик change, полностью симметричный уже существующему у install-тумблера.
Формат общего состояния ook836ServiceState изменён с одного объекта на список объектов — раньше слот вмещал ровно одну услугу (архитектурное решение самой задачи OOK-836, до сих пор державшееся все предыдущие доработки), теперь это массив, чтение сделано обратно совместимым (старый формат, единственный объект, читается как список из одного элемента — на случай, если в хранилище останется что-то, записанное непереписанным файлом). Единая точка синхронизации applyState() на каждое изменение перечитывает список и обновляет разом оба виджета на странице и оба переключателя в модалке — поэтому включение в любом из четырёх мест мгновенно отражается во всех остальных.
Побочная регрессия, найденная и исправленная в процессе, а не запрошенная напрямую: у файла корзины (ook-836-cart-mobile-tobe.html) осталась собственная функция сидирования демо-состояния по умолчанию (не убиралась в доработке 3, т.к. правка тогда была скопирована только в файл карточки OOK-839). Сидирование гейтится флагом ook836ServiceStateInitialized, который раньше выставляла любая из нескольких страниц семейства OOK-836 — но с доработки 3 карточка товара OOK-839 этот флаг больше не выставляет. В результате при переходе из OOK-839 (где реальный выбор пользователя уже записан) в корзину — корзина видела «флаг не стоит» и молча перезаписывала настоящий выбор своим дефолтом на одну услугу, теряя второй. Обнаружено вручную при проверке через Playwright (реальный выбор из двух услуг на входе в корзину превращался в одну). Исправлено удалением сидирования из файла корзины — тот же принцип «дефолт — пусто», что уже применён к карточке товара в доработке 3.
Отображение в корзине переведено с одного вложенного слота на два фиксированных (data-nested-slot="0" и "1"), каждый заполняется из своего элемента списка; обёртка использует display:flex с gap, а не margin между элементами — hidden-слот не участвует в раскладке flex, поэтому лишнего отступа нет, если показана только одна из двух услуг. Кнопка «Удалить» у отдельной услуги теперь снимает конкретный id, а не весь слот; «Удалить» у товара каскадно убирает все привязанные к нему услуги разом, тост называет каждую («Установка… и Гарантия… удалены» с правильным окончанием глагола). Чекаут (ook-836-checkout-mobile-tobe.html) не потребовал изменений — он уже строит список позиций по чекбоксам корзины через общий ITEM_CATALOG, а не через ook836ServiceState напрямую.
Сознательно не тронуто (задокументировано как открытый вопрос): десктопная карточка товара, отдельная мобильная карточка товара самой задачи OOK-836, десктопные корзина/чекаут и карточка услуги по-прежнему ожидают старый формат состояния (один объект). Полный перенос списочной модели во все файлы OOK-836 — отдельная, более крупная доработка, не входила в скоуп этого раунда.
Проверено через Playwright: включение «Установка» на виджете → сразу отражается в модалке; включение «Гарантия» в модалке (при уже включённой «Установка») → обе остаются включены везде (2 виджета + 2 переключателя модалки); выключение одной услуги не трогает другую; переход в корзину показывает оба вложенных слота с верными названием/артикулом/ценой, сумма корректна (52 821 ₽ / +528); каскадное удаление товара называет обе услуги во множественном числе и полностью очищает состояние; удаление одной услуги через кнопку «Удалить» у слота оставляет вторую нетронутой; чекаут показывает оба чипа услуг, итог верен (56 711 ₽ = 41 731 товары + 12 690 услуги + 2 290 доставка) — без ошибок в консоли на всех трёх файлах.
OOK-836Сегодня услуги установки существуют только как допродажа, привязанная к конкретному товару: виджет на карточке техники и чип в корзине не добавляют настоящий товар в заказ, а создают лид (заявку) в стороннюю компанию. У услуги нет собственной карточки, артикула и цены как у отдельного товара — её нельзя найти в каталоге, нельзя купить без покупки техники у нас, и её продажи невозможно нормально учитывать отдельно от товарных.
Бизнес хочет превратить услуги установки в полноценные товары каталога: со своей карточкой, ценой и артикулом, продаваемые как вместе с техникой, так и самостоятельно — с чистой передачей оплаченного заказа внешнему подрядчику (MyTech), который физически оказывает услугу.
Каждая услуга установки — отдельный товар (артикул) со своей ценой. Услуг много (порядка двадцати, список будет пополняться), каждая привязана к определённой категории/типу техники — например, «Установка встроенного холодильника» относится ко всем товарам категории «Встроенные холодильники». У услуги — собственная карточка товара (как у обычной техники) и отдельная ветка каталога «Услуги», через которую услугу можно найти и купить независимо, без покупки техники у нас — в том числе для техники, купленной не у нас, и для товаров сторонних DBS-продавцов (сами DBS-продавцы услуги не оказывают).
На карточке товара сохраняется существующий блок допродажи услуги, но меняется его механика: раньше клик создавал лид в стороннюю компанию, теперь — добавляет в корзину конкретный артикул услуги, соответствующий категории этого товара (та же услуга, что доступна и через отдельную карточку, не дублирующаяся сущность). Гарантия — второй существующий тип допуслуги — в эту задачу не входит и остаётся в прежней схеме. В прототипе гарантия дополнительно показана по тому же паттерну, что и установка, — как демонстрация масштабируемости решения на втором примере; включение гарантии в скоуп задачи бизнесом не подтверждено, это решение уровня прототипа.
Услуги требуют обязательной онлайн-предоплаты (в отличие от товаров, где доступна в том числе оплата при получении) — бизнес-ограничение, продиктованное подрядчиком MyTech: он не должен получать заказ на услугу до её фактической оплаты. Из-за этого заказ, содержащий и товары, и услуги, технически расщепляется на независимые заказы по типу блока — по аналогии с уже существующим дроблением по продавцам в рамках DBS: услуги всегда формируют отдельный блок «Услуги» с обязательной онлайн-предоплатой, а товарные блоки сохраняют текущий выбор способа оплаты, включая оплату при получении.
Услуги должны допродаваться по всей воронке, включая страницу «Спасибо за заказ» (TYP) — но в этой итерации TYP не проектируется полноценно: сначала нужно увидеть текущую реализацию страницы на сайте и в приложении и доработать её, а не проектировать заново.
Нужна аналитика по продажам услуг отдельно от товаров: сколько услуг продано и через какой канал (виджет на карточке товара / переход из каталога или карточки услуги / самостоятельная покупка без товара), конверсия виджета, средний чек услуги, доля заказов, содержащих услугу. Отдельно, когда будет спроектирован TYP, — конверсия допродажи услуги на этом экране. Точный состав метрик — на усмотрение дата-аналитика.
Каждая услуга — самостоятельный товар со своей карточкой (аналогично карточке техники): название, описание, цена, добавление в корзину. Услуга закреплена за определённой категорией/типом техники и не зависит от конкретной модели — цена фиксированная, как у любого другого товара со своим артикулом. Услуг порядка двадцати, список будет пополняться — карточки должны заводиться как обычные товары каталога, стандартным процессом, без отдельного инструмента.
Одна и та же услуга, купленная через виджет на карточке товара и отдельно через свою карточку, — два независимых элемента заказа, а не одна переиспользуемая позиция.
Прототип собран — см. Макеты. У экрана нет as-is (на реальном сайте такой карточки сегодня нет), поэтому важна не только сама вёрстка, но и обоснование, какие блоки карточки товара для услуги не нужны, а какие нужно добавить (оплата только онлайн, что входит в услугу, как проходит визит мастера, FAQ) — подробно в комментариях к прототипу.
На карточке товара (техники) сохраняется существующий блок предложения услуги — это основная точка её продажи. Меняется механика: клик добавляет в корзину конкретный артикул услуги, соответствующий категории этого товара, вместо создания лида в стороннюю компанию. У товара не может быть больше одной релевантной услуги установки одновременно — виджет не предлагает выбор между несколькими вариантами.
То же добавление доступно и прямо из корзины, если товар там уже есть, а услуга к нему ещё не добавлена, — не только с карточки товара.
Услуги собраны в отдельной ветке каталога «Услуги», не растащены по категориям техники, — самостоятельная точка входа, позволяющая купить услугу без привязки к покупке техники у нас, в том числе для техники, купленной не у нас, и для товаров DBS-продавцов. С учётом количества услуг (порядка двадцати и растёт) ветке, вероятно, нужны подкатегории по типу техники (холодильники / стиральные машины / …) — финальную структуру предстоит уточнить с дизайнером/категорийным менеджером.
Услуги требуют обязательной онлайн-предоплаты — товары в том же заказе сохраняют любой доступный способ оплаты, включая оплату при получении. Если в заказе одновременно есть товары и услуги, заказ технически расщепляется на независимые заказы по типу блока, по аналогии с дроблением по продавцам в рамках DBS: услуги всегда формируют один общий блок «Услуги» (независимо от того, у какого продавца куплен связанный товар — услугу в любом случае оказывает подрядчик ХЛД), с обязательной онлайн-предоплатой только на эту часть.
Рассмотренные и отклонённые альтернативы: (а) отключать оплату при получении для всего заказа целиком при наличии услуги — плохой UX, наказывает не связанную с услугой часть покупки, вероятная потеря конверсии на товарах; (б) один заказ с частичной предоплатой (услуга оплачена, товар — по факту) — избыточно сложная модель статуса оплаты, для которой пришлось бы городить отдельную статус-машину вместо переиспользования существующей модели «заказ оплачен / не оплачен».
Оформление в этом случае создаёт несколько независимых заказов, а не один заказ с несколькими поставками.
MyTech — внешний подрядчик, оказывающий услуги установки. Жёсткое бизнес-ограничение: подрядчик не должен получать заказ на услугу до момента её фактической оплаты клиентом. Сама интеграция (передача данных клиента и состава заказа услуги в MyTech после оплаты) — вне UI-скоупа прототипа, фиксируется как зависимость бэкенда.
Блок «Услуги» в чекауте — самостоятельный блок на уровне блоков доставки, наравне с блоком ХЛД и блоками DBS-продавцов, не вложен ни в один из блоков продавца: услугу в любом случае оказывает MyTech, независимо от того, у кого куплен связанный товар.
По умолчанию — один общий адрес и один слот времени на весь блок услуг, как один визит мастера; при необходимости пользователь может развернуть блок и задать отдельный адрес/время для конкретной услуги. Если в заказе только услуги без единого товара — блока доставки товара нет вообще, есть только блок услуг со своим адресом. Время оказания услуги выбирается тем же виджетом слотов, что уже используется для выбора времени доставки товара.
Услуги, не требующие визита мастера (например, гарантия), в этот адресный блок не попадают — они добавляются в заказ отдельной строкой стоимости при оформлении, без своего адреса и времени.
Открытый вопрос — не решено, в какой момент пробивается чек по услуге. См. открытые вопросы.
Позиции по услугам показываются в чеке отдельным блоком «ОТДЕЛИМЫЕ УСЛУГИ», не смешиваясь с товарными позициями.
Услуги допродаются на странице «Спасибо за заказ» (TYP). Экран показывает одно из двух состояний. Если в заказе нет услуги — блок допродажи, предлагающий добавить установку/гарантию к уже купленному товару. Если услуга в заказе уже есть — вместо допродажи показан статус каждой купленной услуги (что произойдёт дальше — например, что мастер свяжется для согласования визита); повторно эта же услуга не предлагается.
Между чекаутом (адрес/дата/способ оплаты) и страницей «Спасибо за заказ» — два промежуточных шага. «Подтверждение заказа» — read-only сводка выбранного на предыдущем шаге, с той же группировкой на независимые блоки, что и чекаут (ХЛД / DBS-продавец / услуги, см. п.4 и п.6): каждый блок подтверждается отдельно, как отдельный будущий заказ. Дальше — переход на страницу оплаты; заказ к этому моменту уже создан в системе со статусом «не оплачен» — его можно найти и оплатить позже в личном кабинете, если оплата не была завершена сразу.
Поверх обычных to-be-экранов собран прямой демо-путь по всей воронке — для отправки ссылкой человеку, который проходит его сам, без комментариев автора. Старт — карточка услуги «Установка встроенного холодильника», услуга ещё не в корзине. Дальше — корзина → чекаут → подтверждение заказа → оплата (заглушка, см. п.10) → «Спасибо за заказ», с минимумом развилок (по сути одна: добавить услугу или пропустить). Клик/тап мимо кликабельных зон на секунду подсвечивает то, что реально продолжает сценарий на этом экране — подробности подхода в базе знаний, Правило 11.
Два готовых пресета стартовых данных, каждый гарантированно стартует без добавленных услуг: «Один товар» — только свой товар, без DBS (десктоп / моб.); «Товар + DBS» — тот же товар плюс DBS-товар, показывает дробление корзины на независимые блоки (десктоп / моб.).
https://drugtolik.ru/holodilnik/index.html?task=OOK-836
Прикрепить ссылку/задачу на макеты
OOK-836Внутренний журнал изменений по датам — не для дизайнера/аналитика, но полезен при дальнейших доработках. Актуальные требования — в соседнем документе «Требования к задаче».
Постановка задачи разобрана по пунктам, продакт-менеджеру заданы уточняющие вопросы по каждому из девяти пунктов постановки плюс несколько дополнительных (перенос даты/времени услуги, отказ/возврат, статусы, слоты, DBS-продавцы). По итогам обсуждения:
ook-836-typ.html), доработка — после того как будет показана текущая реализация страницы.Оставлены открытыми: момент выдачи чека по услуге, отказ/возврат, статусы услуги в заказе, финальная структура подкатегорий ветки «Услуги», возможность одного визита мастера на несколько адресов, точная механика TYP.
Пользователь прислал полные скриншоты карточки товара (десктоп и моб.) реального сайта — товар «Двухкамерный холодильник Indesit ITS 5200 NG Темно-серый». Собраны ook-836-product-card-asis.html и ook-836-product-card-mobile-asis.html: галерея, блок покупки (рейтинг, артикул, цена/скидка, бонусы, рассрочка, кнопки «В корзину»/«Купить в 1 клик», доставка/самовывоз, блок продавца), «Часто покупают вместе», табы «Характеристики/Отзывы/Сертификаты», двухколоночный блок «Описание» + таблица характеристик, и полный набор каруселей товаров вплоть до «Аксессуары для…» — по подписям разделов, читаемым на скриншотах. Шапка/хлебные крошки/подвал переиспользованы почти дословно из ook-834-landing-bonus.html/-mobile (тот же паттерн «rich-header», уже сверенный со скриншотами в задаче OOK-834), а не собраны заново с нуля.
Открытый момент, важный для дальнейшей работы: на присланных скриншотах (сильно сжаты по высоте из-за длины страницы) не удалось однозначно разглядеть блок допродажи услуги установки, который по базе знаний (раздел 13) должен где-то на карточке присутствовать. В этом as-is он не смоделирован — сознательно, а не по недосмотру (см. requirements-modal обоих файлов). Прежде чем проектировать to-be с доработанным виджетом (пункт 2 требований OOK-836), нужен более чёткий/крупный скриншот именно блока покупки, либо явное подтверждение, где на карточке этот блок сейчас расположен.
Сознательные упрощения (обычная практика для as-is по скриншотам, см. пример OOK-834): значения таблицы характеристик — правдоподобные, но не сверенные посимвольно с реальным листингом (разрешение скриншота не позволило прочитать таблицу точно); товарные карточки во всех каруселях — переиспользуемый демо-набор в 8–10 товаров, не уникальный набор на каждую секцию; фото товара — заглушка-иконка вместо реальной фотографии; поиск, фильтры и табы — декоративны.
Пользователь честно указал, что доработка 2 «вообще не похожа на реальную карточку» — по существу верно: скриншоты были полными страницами очень большой высоты, сжатыми при отображении до ~2000px, и на таком масштабе текст/цвета/расположение блоков были не читаемы, а не просто «немного неточны». Прототип из доработки 2 был по факту не as-is, а обобщённая карточка товара «вообще», собранная по типовым паттернам e-commerce, а не по факту со скриншота — это было прямо признано пользователю.
После восстановления подключения Playwright MCP пользователь дал прямую ссылку на реальный товар — holodilnik.ru/refrigerator/two_chambered_refrigerators/beko/b1rcsk272w/ (Beko B1RCSK272W, не Indesit ITS 5200 NG из скриншотов — сознательная замена на полностью проверяемый источник). Both файла (ook-836-product-card-asis.html/-mobile-asis.html) пересобраны с нуля: accessibility-снимок DOM дал точный текст (заголовок, хлебные крошки, описание, полную таблицу характеристик, реальные позиции блока «Аксессуары для…»), getComputedStyle дал точные цвета (шапка/кнопка #00aaff/#079ff9, жёлтый бейдж скидки #ffea31, мятно-зелёные карточки услуг #b5f7e6/#09e5ac), прицельные скриншоты (не полностраничные) подтвердили вёрстку.
Главная находка — реальный виджет допродажи услуг (пункт 2 требований OOK-836) найден и воспроизведён 1:1, включая точную разметку: id="addon_installment_mytech_1" в атрибутах подтверждает, что MyTech уже сегодня технически зашит как провайдер услуги установки. Подробности — в базе знаний, раздел 17 «Отделимые услуги и MyTech». Это отменяет открытый вопрос из доработки 2 («не удалось разглядеть блок услуги») — блок найден, точная разметка задокументирована, и это прямая опора для будущего проектирования to-be.
Существенная правка состава страницы: каруселей «Рекомендуем также» / «Выбор клиентов» / «Часто покупают вместе» / «Вы недавно смотрели», придуманных в доработке 2 по аналогии с другой страницей сайта (категорийный листинг OOK-834), на реальной карточке товара нет. В этой же доработке 3 реально найдены и добавлены только 2 из 9 существующих каруселей («Покупают со скидкой до 15% бонусами», «В корзинах наших покупателей») — остальные 7 (класс .carousel-catalog-products) на момент доработки 3 ошибочно списаны на блокировку Mindbox-доменов в этой сети. Это исправлено в доработке 4 ниже — на самом деле дело было в ленивой подгрузке, не в блокировке.
Дополнительная реальная находка на мобильной версии: «Характеристики»/«Отзывы»/«Сертификаты» на мобильном — не горизонтальные табы (как на десктопе), а вертикальный аккордеон, свёрнутый по умолчанию; при этом виджеты услуг остаются компактными бок о бок, не раскладываются в стек. Это нельзя было бы узнать без прямого доступа к браузеру — на скриншоте эта деталь не была видна и не была бы угадана правильно.
Урок на будущее, зафиксирован явно пользователю и в этой записи: для as-is по реальному сайту скриншот полной страницы — плохой источник, если страница длинная; прямой доступ к браузеру (Playwright: DOM для текста, computed styles для цветов, точечные скриншоты для вёрстки) — кратно надёжнее и должен быть основным способом впредь, скриншоты — только как запасной вариант или для сверки конкретных небольших блоков.
Пользователь указал на два конкретных повода недовольства результатом доработки 3: (1) пропущено много блоков и (2) для страниц за авторизацией (например, личный кабинет) прямой доступ через Playwright вообще не сработает. По второму пункту обсуждён и зафиксирован отдельный подход (не в этой доработке — когда реально понадобится): тестовый/демо-аккаунт компании, если есть, либо пользователь сам копирует outerHTML из DevTools своего авторизованного сеанса — вводить реальный пароль в Playwright для этого не стоит, это чужие персональные данные (заказы, адреса, телефон).
По первому пункту — найдена и исправлена настоящая причина. В доработке 3 запрос к DOM (через textContent.includes() и точечные querySelector) выполнялся без предварительной полной прокрутки страницы — 7 из 9 карусельных блоков товаров подгружаются лениво по мере прокрутки и на момент запроса были пустыми контейнерами без заголовка. Это было ошибочно интерпретировано как блокировку Mindbox-доменов (реальная и отдельная проблема этой сети, но не имеющая отношения к этому случаю) — типичная ошибка «не нашёл → решил, что заблокировано», а не «не нашёл → проверил другую причину».
Правильная дисциплина, применённая в этой доработке: перед любым чтением DOM — механическая прокрутка всей страницы шагами по 800px с паузой между шагами до конца document.body.scrollHeight, чтобы гарантированно вызвать всю ленивую подгрузку; только после этого — инвентаризация блоков по классам (например, все элементы .carousel-catalog-products с их заголовками и позициями), а не точечные проверки по гипотезам вида «есть ли текст X». Это дало все 9 реальных каруселей с реальными товарами и ценами (были известны 2, добавлены ещё 7: «Новинки», «Лучшее по отзывам», «Ищут чаще всего», «Лучшее из Liebherr», «Любимое у покупателей», «Скидка -20% на три товара любых брендов», «Максимальные скидки») — добавлены в оба файла (ook-836-product-card-asis.html/-mobile-asis.html), заодно повторно подтверждено (после полной прокрутки, не до неё), что блока «Часто покупают вместе» на реальной странице по-прежнему нет — это не то же самое, что «не подгрузилось».
Общее правило на будущее, зафиксировано в памяти проекта: полная механическая прокрутка страницы до конца — обязательный первый шаг перед чтением DOM любой длинной страницы через Playwright, а не опциональная предосторожность.
Пользователь остался не удовлетворён и доработкой 4 — не разово по одной жалобе, а с конкретным конструктивным предложением: написать локальный инструмент, который режет длинный full-page скриншот на части фиксированной высоты (по умолчанию 1500px), чтобы каждая часть оставалась читаемой при просмотре, а не сжималась целиком. Создан tools/slice_screenshot.py (Python + Pillow, без внешних зависимостей кроме уже установленного Pillow) — принимает путь к файлу, режет на части с постфиксами _1, _2 и т.д., поддерживает свою высоту среза (--height) и папку назначения (--outdir). Проверен на синтетических изображениях перед использованием.
Инструмент подтвердил свою пользу сразу же. Пользователь дал два оригинальных full-page скриншота с рабочего стола (2880×26387 и 800×19941 — те самые, с которых начиналась работа над as-is в этой задаче) — тот же самый файл, что был нечитаем в доработке 2, после нарезки на 18 (десктоп) и 14 (моб.) частей оказался полностью читаем один в один.
Прочитаны все 18 десктопных частей — и это выявило то, чего не поймать было ни скриншотом целиком, ни точечными DOM-запросами доработки 3–4: на реальной карточке товара есть ещё 3 карусели, идущие ДО табов, сразу после виджетов услуг — «Рекомендуем также», «Выбор клиентов» и «Часто покупают вместе» — плюс «Вы недавно смотрели» после блока характеристик. Итого 13 реальных каруселей, не 9. Доработка 4 не нашла эти четыре, потому что искала по одному конкретному CSS-классу (.carousel-catalog-products) — эти четыре, судя по всему, используют другую разметку, то есть даже «правильная» дисциплина (сначала прокрутка, потом инвентаризация) может быть неполной, если инвентаризация ищет по одному заранее известному признаку, а не читает страницу целиком.
Ещё одна находка — «Часто покупают вместе» оказалось совсем не тем, чем его придумали в самой первой версии (доработка 1/2). Это обычная карусель товаров (стиральные и посудомоечные машины — сопутствующая техника), с той же структурой карточек, что у остальных каруселей — а не виджет с чекбоксами, миниатюрами и итоговой суммой, который был построен по одной лишь надписи на нечитаемом скриншоте. Фиктивный bundle-виджет из десктопной версии полностью убран.
Заодно выяснилась и причина путаницы: скриншоты в доработках 1–2 были сделаны для другого товара (Indesit ITS 5200 NG), а доработки 3–4 намеренно работали с Beko B1RCSK272W (выбранным как «полностью проверяемый источник» до появления инструмента нарезки). Теперь, когда скриншоты снова читаемы, вернулись к оригинальному товару пользователя — Indesit ITS 5200 NG Темно-серый — и картинки, и карточка снова говорят об одном и том же товаре. Оба файла (ook-836-product-card-asis.html/-mobile-asis.html) пересобраны: цена/скидка/бонусы/рассрочка/цены виджетов услуг (у гарантии цена зависит от цены товара — 8 730 ₽/243 ₽ в месяц против 6 610 ₽/184 ₽ у более дешёвого Beko), полное описание и таблица характеристик — всё по данным из нарезанных скриншотов, все 13 каруселей — с реальными товарами/ценами (кросс-сверено: 9 «поздних» каруселей совпадают между Beko и Indesit почти дословно — похоже, это общие/не персонализированные под конкретный товар блоки, а 4 «ранних» — товар-специфичны).
Итоговый урок, отличается от вывода доработки 4: дисциплина «сначала прокрутка, потом инвентаризация по known-классам» полезна, но недостаточна сама по себе — она может пропустить контент, использующий не тот класс, который вы искали. Нарезанные на читаемые части скриншоты — не запасной вариант «на крайний случай», а полноценный, взаимодополняющий метод: DOM/computed styles дают точный текст и цвета, но требуют знать, что искать; скриншот показывает всё, что физически есть на странице, независимо от разметки — вместе они кроют слепые зоны друг друга. Оба метода стоит использовать вместе для крупных as-is, не выбирать один вместо другого. Этот урок вынесен в базу знаний как «Правило 6» раздела «Подход к созданию прототипов» — не только частный вывод для этой задачи.
Две точечные правки по итогам просмотра пятой версии. Ни одна услуга не выбрана по умолчанию — раньше тумблер «72 часа на ремонт…» (гарантия) был включён по умолчанию (так было на реальном сайте на момент съёмки скриншота), но для прототипа это осознанно неверный дефолт: оба тумблера в обоих файлах (десктоп и моб.) теперь выключены изначально.
Все 14 каруселей (13 товарных + аксессуары) сделаны явно листаемыми — карточки продублированы (где нужно — с повторами, специально ради демонстрации самого факта прокрутки, а не уникальности содержимого) до 8 штук на десктопных каруселях и 7 на мобильных, так чтобы ряд карточек гарантированно не помещался в видимую область ни на десктопе, ни тем более на мобильном (там раньше было всего по 2 карточки — прокручивать было нечего). Заодно найден и исправлен баг: карусель «Аксессуары» использует свой класс .accessory-card/.m-accessory-card, а не общий .product-card — у него не было фиксированной ширины (flex: 0 0 …px), из-за чего даже 8 карточек просто сжимались, чтобы поместиться, вместо того чтобы вызвать прокрутку. Добавлена фиксированная ширина, проверено через scrollWidth > clientWidth на всех 14 каруселях в обоих файлах — все листаемые.
Собран базовый набор целевых (to-be) прототипов для всех трёх экранов задачи: ook-836-product-card-tobe.html/-mobile-tobe.html, ook-836-cart-tobe.html/-mobile-tobe.html, ook-836-checkout-tobe.html/-mobile-tobe.html. Карточка товара построена на структуре as-is (доработка 5–6); корзина и чекаут — не с нуля, а поверх существующего to-be OOK-696 (ook-696-cart-tobe.html/ook-696-checkout-tobe.html), поскольку у OOK-836 нет своего as-is этих двух экранов и оба напрямую наследуют DBS-механику дробления корзины/чекаута, разработанную в OOK-696.
Карточка товара: визуальных изменений почти нет (см. базу знаний, раздел 17 — реальный виджет уже выглядит как «добавить в корзину», разница только в данных). Включение тумблера «Профессиональная установка техники» теперь реально добавляет артикул услуги в корзину (счётчик в шапке растёт, под тумблером появляется зелёная отметка «Добавлено в корзину» вместо подписи про гарантию на работу, показан артикул). Виджет «Гарантия Премиум» не тронут — вне скоупа задачи.
Корзина: чип «Установка», ранее вложенный в карточку товара (.services-row внутри .cart-item-body, паттерн OOK-696), убран у товаров, где он был (Haier, Новатек-Электро) — установка теперь отдельная строка в новой группе «Услуги» под основным списком, оформленная как обычный товар (миниатюра/название/артикул/цена/«Удалить»), без степпера количества. Группа помечена бейджем «Оплата онлайн заранее» (мятный цвет, тот же, что у виджета на карточке). Чип «Гарантия «72 часа»» — без изменений, вне скоупа.
Чекаут: добавлен независимый блок «Установка техники» — не вложен ни в один блок продавца (ХЛД/DBS), появляется только если в заказе есть хотя бы одна услуга, содержит только адрес и время (без «Курьером/Самовывоз», без своей стоимости доставки — цена уже в самой услуге), с постоянно видимой мятной плашкой про обязательную предоплату онлайн (ограничение MyTech). Переиспользован существующий механизм блокировки товаров по способу оплаты (изначально сделанный в OOK-696 для «Яндекс Сплит»): при выборе оплаты «При получении»/«По счету» позиции блока «Установка техники» так же деактивируются (приглушение + красный значок с тултипом), исключаются из «Итого», появляется отдельное предупреждение — второй такой же компонент рядом с исходным алертом Яндекс-Сплит, не смешан с ним. Строка «Услуги» в сводке (существовала и раньше, для гарантии из чипов корзины, была скрыта по умолчанию) теперь суммирует ещё и артикулы установки — общая сумма «доплат за услуги», при этом «В корзине N товаров» и сумма товаров больше их не включают.
Сознательное упрощение, явно не реализованное: требования (п.6) допускают «развернуть» блок услуг и задать отдельный адрес/время для конкретной услуги, если их в заказе несколько с разными адресами, — в прототипе это не смоделировано, всегда один общий адрес/время на все услуги сразу. Причина — открытый вопрос «может ли один визит мастера покрыть услуги на товары из разных блоков доставки» всё равно не решён с MyTech, так что разворачивание пока негде было бы содержательно применить.
Проверено через Playwright: полный путь карточка → добавление услуги → корзина → чекаут → выбор способа оплаты «При получении» → корректное исключение услуг из «Итого» — без ошибок в консоли на всех шести файлах, суммы сходятся (товары/услуги/бонусы/итого пересчитываются верно в обоих направлениях — при исключении и при возврате). Карточка OOK-836 на index.html перестроена в .proto-versions (as is/to be колонки), по образцу карточки OOK-696.
ook-836-service-card-tobe.html/-mobile-tobe.html) — новый экран, п.1 требованийСобрана карточка отдельной услуги «Установка встроенного холодильника» (тот же артикул УСТ-247-ВСТР и цена 2 360 ₽, что уже фигурируют в виджете карточки товара, корзине и чекауте — единая демо-услуга через всю цепочку прототипов OOK-836). У экрана нет as-is: на реальном сайте отдельной карточки товара-услуги не существует, поэтому анализ строился не на сравнении со скриншотом, а на разборе карточки товара (ook-836-product-card-tobe.html) блок за блоком — что переносится, что убирается, что нужно добавить — с точки зрения пользователя, который решает, покупать ли услугу.
Убрано у карточки товара как не имеющее смысла для услуги: 360°-галерея с ракурсами (заменена на один статичный иллюстративный блок), рассрочка/бейдж Яндекс Сплит (прямо противоречит бизнес-правилу обязательной 100% предоплаты услуг), «Самовывоз из магазина»/«Доставка» (услугу не забирают и не привозят — её оказывает мастер по адресу заказа), виджет допродажи услуг (нельзя купить услугу к услуге), таблица физических характеристик (высота/цвет/энергокласс и т.п. неприменимы), строка бренда/скидка на товар.
Добавлено, обоснование — что важно человеку, который решает купить услугу: «Что входит в услугу» (чек-лист сразу у блока покупки — первый вопрос «а что конкретно сделает мастер»), «Как это работает» (4 шага — покупка услуги растянута во времени до визита мастера, в отличие от разовой покупки товара, шаги снимают тревожность), явная мятная плашка «Оплата онлайн заранее» прямо в блоке покупки (честно показано до клика «Добавить в корзину», а не сюрпризом на чекауте), FAQ (нужно ли быть дома, можно ли перенести время, что покрывает гарантия на работу — доверие к разовой услуге от постороннего человека дома ниже, чем к обычной покупке), отзывы (сохранены — качество работы мастера пользователь не может оценить заранее по фото), «Другие услуги» вместо каруселей случайных товаров (осмысленный кросс-селл только внутри самой категории «Услуги»), «Подходит для: Встроенные холодильники» — явный ответ на вопрос «а точно ли эта услуга мне нужна».
Одна из четырёх FAQ-карточек («Что если мастер не сможет начать работу?») намеренно оставлена как открытый вопрос с видимой красной пометкой прямо на странице — честного ответа для него пока нет; ответ про перенос даты/времени, наоборот, написан консистентно с уже зафиксированным фактом задачи (переносится напрямую с мастером/поддержкой, не через сайт).
Ссылка «Подробнее ›» у виджета «Профессиональная установка техники» на карточке товара (десктоп и моб.) обновлена — раньше вела в никуда (#), теперь ведёт на эту карточку услуги, замыкая цепочку карточка товара → карточка услуги → корзина → чекаут.
Попутно найден и исправлен реальный CSS-баг (тот же паттерн, что уже фиксировался в проекте: класс с безусловным display: flex перебивает браузерное правило [hidden]{display:none} по специфичности) — бейдж счётчика корзины в шапке (.hru-icon-badge) был виден сразу при загрузке страницы, хотя должен быть скрыт до первого добавления в корзину. Баг воспроизвёлся в обоих файлах, использующих этот класс, — ook-836-product-card-tobe.html и новой ook-836-service-card-tobe.html; исправлено добавлением явного .hru-icon-badge[hidden]{display:none} в оба. Проверено через Playwright (getComputedStyle до и после клика).
Открытые вопросы: содержание чек-листа/шагов/FAQ — правдоподобный, но придуманный для прототипа контент, реальный текст нужно согласовать с MyTech; страница-листинг ветки каталога «Услуги» (п.3 требований) не смоделирована — это только карточка одной услуги, ссылки на категорию и карусель «Другие услуги» ведут в #; возможность скидки/промо на услугу не проработана; кнопка «Добавить в корзину» на этой карточке — отдельная демо-реализация (свой счётчик), не связана через localStorage с остальными прототипами OOK-836.
По просьбе пользователя — три связанных правки, две механические (упрощение) и одна архитектурная (пересмотр способа привязки услуги к товару).
1. Упрощение демо-данных корзины и чекаута. Убран блок «Товары не в наличии» из корзины (2 позиции). Набор товаров сокращён до минимально необходимого для демонстрации механики: 1 товар «Холодильник.Ру» (Haier BCF5261WRU), 1 DBS-товар (болт КМ-Профиль), 1 услуга (Установка встроенного холодильника) — вместо прежних 4 товаров/2 DBS-продавцов/2 услуг. Titanium Masters, Новатек-Электро и вторая услуга убраны из ook-836-cart-tobe.html/-mobile-tobe.html и ook-836-checkout-tobe.html/-mobile-tobe.html (блок «Новатек-Электро» удалён из чекаута целиком, не просто скрыт). Вся убранная функциональность (несколько DBS-продавцов одновременно, блок недоступных товаров) по-прежнему полностью описана в базовом to-be OOK-696 — упрощение касается только демо-данных задачи OOK-836, не логики OOK-696. Попутно найден и исправлен реальный баг: после удаления блока «Новатек-Электро» строка сводки «Доставка: Новатек-Электро» осталась бы в DOM без обработчика видимости (JS больше не перебирает ключ novatek) и была бы видна вечно — убрана вместе с блоком.
2. Разобран вопрос: приводит ли добавление услуги через тумблер на карточке товара и через отдельную карточку услуги (ook-836-service-card-tobe.html) к одному и тому же результату в корзине/чекауте? До этой правки — нет: корзина писала под названием услуги «для Haier BCF5261WRU» (конкретный товар), при этом по требованиям (п.1) услуга привязана к категории техники, а не к модели, — то есть корзина утверждала связь, которой в модели данных не существует. При добавлении через отдельную карточку услуги эта информация в принципе недоступна (там нет контекста, из какой карточки товара пришёл пользователь), значит два способа добавления физически не могли бы давать одинаковый результат, пока в корзине жила строка про конкретную модель.
Решение: подпись артикула везде (виджет на карточке товара, корзина, чип на чекауте) переведена на уровень категории — «для категории «Встроенные холодильники»» вместо «для Haier BCF5261WRU». Теперь оба способа добавления услуги производят идентичный результат, потому что оба честно оперируют одним и тем же уровнем детализации, который реально есть в данных. Заодно исправлена реальная рассинхронизация цены: в корзине/чекауте артикул УСТ-247-ВСТР стоил 3 520 ₽, а на карточке товара и карточке услуги — 2 360 ₽; унифицировано до 2 360 ₽ везде.
3. Тумблер виджета установки на карточке товара заменён кнопкой «Добавить в корзину». Отдельно разобран вопрос: что делать с тем, что тумблер сбрасывается в выключенное положение при обновлении страницы карточки товара, даже если услуга уже лежит в корзине с прошлого раза (визуально врёт о состоянии)? Два варианта: (а) научить тумблер при загрузке проверять содержимое корзины и сразу показываться включённым, если услуга там уже есть; (б) убрать тумблер вообще. Выбран (б): тумблер как элемент управления семантически означает «локальное состояние здесь и сейчас» (как переключатель настройки), а не «положить товар в корзину навсегда» — это два разных действия, случайно упакованных в один визуальный компонент. Кнопка «Добавить в корзину → Перейти в корзину →» (один клик — необратимое действие, как у обычного товара) честнее отражает, что на самом деле происходит, и делает интерфейс идентичным кнопке на карточке услуги — теперь оба входа в добавление услуги выглядят и ведут себя одинаково. Виджет «Гарантия Премиум» не тронут — сохраняет свой тумблер, вне скоупа задачи.
Явно не решено этой заменой (зафиксировано как открытый вопрос в модалках обеих карточек товара): кнопка по-прежнему не проверяет at load, есть ли услуга уже в корзине — при обновлении страницы всегда возвращается в состояние «Добавить в корзину». Вариант (а) выше остаётся нерешённым вопросом для реальной реализации, не для этого прототипа — у статичных HTML-файлов нет общего состояния корзины, которое можно было бы проверить.
Проверено через Playwright: полный путь карточка → добавление услуги (кнопка меняется, счётчик растёт) → переход в корзину → корзина (2 товара + 1 услуга, суммы 99 511 ₽/+992 бонуса) → чекаут (блок Новатек-Электро отсутствует в DOM, суммы 103 401 ₽) → «При получении» (услуга корректно исключается из «Итого», сумма 101 041 ₽) — без ошибок в консоли на всех изменённых файлах (десктоп + моб.).
Пользователь прямо указал на цену решения доработки 9 (категорийная привязка + кнопка вместо тумблера): теряется возможность видеть услугу рядом с её товаром в корзине, а «одинаковый результат для двух путей добавления» на деле означало «тумблер тоже забывает, к какому товару он относится» — то есть решалась не та проблема. Задача — изучить мировую практику и предложить модель без костылей (обработки «а что если товар удалили» и т.п.), но с сохранением UX-пользы (услуга видна рядом с товаром) и высокой конверсией.
Разобрана практика Amazon (планы защиты Asurion), Best Buy (Geek Squad), IKEA (сборка мебели), Lowe's/Home Depot (установка техники), Apple (AppleCare+). Общий паттерн у всех: услуга при добавлении «в довесок» к товару получает реальную ссылку на конкретную строку заказа (не абстрактную категорию), показывается вложенной/сгруппированной с этим товаром, и удаление товара каскадно удаляет услугу (без блокирующего подтверждения — просто тихо + короткий тост). Apple отдельно показывает решение для случая «без товара» (услуга покупается позже, для уже купленного устройства) — не выдумывает мягкую привязку, а требует явную идентификацию (серийный номер); никто не размывает привязку до уровня категории.
Итоговая модель: общее состояние localStorage['ook836ServiceState'] (контракт: {itemId, linkedItemId, addedVia}), которое читают и пишут карточка товара, карточка услуги и корзина. linkedItemId — id товара в заказе, к которому привязана услуга, или null. addedVia — 'widget' (тумблер на карточке товара, который точно знает текущий товар) или 'catalog' (отдельная карточка услуги, у которой контекста товара нет вообще).
ook836ServiceState), а не сбрасывается. Включение/выключение реально добавляет/убирает услугу из корзины с привязкой к этому товару.Затронуты все шесть файлов задачи (карточка товара, карточка услуги, корзина — десктоп и моб.). Чекаут не менялся — он как читал выбор через ook696CartSelection/ITEM_CATALOG, так и продолжает, механизм сбора данных в корзине остался прежним (просто источник строки услуги в DOM теперь динамический, а не статичный).
Проверено через Playwright: тумблер на карточке товара честно отражает состояние при каждой загрузке в обе стороны (включил на карточке → виден вложенным в корзине; удалил в корзине → тумблер выключен при следующем визите на карточку); путь через карточку услуги добавляет без привязки, показывается отдельной группой; каскадное удаление корректно убирает только реально привязанную услугу и не трогает непривязанную; чекаут считает суммы верно после обоих путей добавления — без ошибок в консоли на всех шести файлах.
Пользователь пришёл к целевому виду всей задачи и попросил проверить и переделать все прототипы по пяти пунктам сразу: (1) нужны и виджет в карточке, и карточка отдельной услуги; (2) виджет нужен и в корзине; (3) в корзине услуга отображается двумя способами (вложенная/отдельная) — по способу добавления; (4) в корзине установка и гарантия должны выглядеть одинаково в виджете; (5) на чекауте каждая услуга — отдельный товар, в миничеке — отдельные строки «Установка»/«Гарантия»; отдельно — карточка услуги не должна радикально отличаться от карточки товара, «дорогие» решения (новая сетка) не нужны, «дешёвые» (убрать карусели) — да. Затронуты все восемь файлов задачи (карточка товара, карточка услуги, корзина, чекаут — десктоп и моб.).
Формат общего состояния ook836ServiceState перенесён на список услуг во всех файлах (было — только в мобильной корзине и мобильной карточке товара OOK-839, десктоп и остальные файлы OOK-836 ещё жили на старом формате «одна услуга»). Установка и гарантия теперь равноправные, не взаимоисключающие услуги — тот же контракт, что уже был обкатан в задаче OOK-839.
Легаси-чип «Гарантия «72 часа»» (унаследован из OOK-696, вне скоупа) убран только у Indesit ITS 5200 NG — заменён на настоящую «Гарантия Премиум» как отдельную услугу; у КМ-Профиль [болт] чип остался без изменений, эта задача его не касается. Держать на одном товаре одновременно два по-разному устроенных и по-разному оценённых «гарантия»-предложения было бы противоречиво.
Новый виджет добавления услуги прямо из корзины — если у товара нет одной или обеих услуг, вместо неё показывается предложение добавить (тот же мятный виджет с флажком-переключателем, что и на карточке товара), без перехода на другую страницу. Установка и гарантия используют один и тот же компонент .cart-addon-widget — визуально идентичны, как и просили.
Карточка услуги пересобрана с нуля. Прежняя версия (доработка 8) была отдельным дизайном — чек-лист «Что входит», 4-шаговый процесс, FAQ, отдельная секция отзывов. Новая версия — копия реальной карточки товара с минимальными отличиями: убраны карусели рекомендаций (единственное, что реально стоило убрать — не имеет смысла для услуги, дёшево), рассрочка/Сплит (противоречит правилу обязательной предоплаты), 360°-галерея (нечего фотографировать под разными ракурсами) и самовывоз/доставка (заменены на «дата и время визита» в том же визуальном слоте). Всё остальное — та же вёрстка, тот же грид, что у товара. Один файл на платформу обслуживает обе услуги через параметр ?service=install-haier / ?service=warranty-premium — «Подробнее ›» на обоих виджетах карточки товара ссылается на нужный вариант.
Чекаут: добавлена запись warranty-premium в десктопный ITEM_CATALOG (мобильный уже имел её после OOK-839). Комбинированная строка «Услуги» в миничеке разделена на три: новые «Установка» и «Гарантия» (по одной на каждую отдельную услугу-каталожную позицию, скрыты, если услуги нет в заказе) плюс оставшаяся строка легаси-чипов, переименованная в «Услуги (гарантия «72 часа»)», чтобы не путать с новой «Гарантия». Суммы не задваиваются — старая строка теперь считает только легаси-чипы.
Проверено через Playwright на обеих платформах: оба тумблера на карточке товара пишут в общий список; карточка услуги с параметром ?service= корректно показывает нужный вариант и состояние «в корзине»; виджет добавления в корзине показывает только недостающие услуги и пропадает, когда добавлены обе; оба вложенных слота отображаются идентично; легаси-чип виден только у болта; чекаут показывает три раздельные строки с верными суммами (установка 2 360 ₽, гарантия 8 730 ₽, легаси-чип 1 600 ₽), итог верен (56 711 ₽) — без ошибок в консоли на всех восьми файлах.
Пользователь посмотрел результат доработки выше и указал на 6 конкретных проблем. Разбор и правка каждой — ниже, в порядке пунктов из постановки.
1–4 (корзина) имели один и тот же корень: параллельное существование двух разных визуальных компонентов для «услуги ещё нет» (большой мятный .cart-addon-widget) и «услуга уже добавлена» (компактная .cart-item.is-nested) — само наличие двух состояний создавало и лишнюю визуальную тяжесть виджета, и почву для расхождения вида между блоками. Решение — не точечный фикс, а объединение: теперь под каждым товаром всегда показываются готовые компактные строки с флажком на каждую доступную услугу; флажок и есть факт присутствия услуги в корзине (включён = услуга в заказе и привязана к этому товару; выключение — полное удаление, не просто сокрытие). Тот же компонент, что раньше был только «уже добавлено», используется всегда — второй, более тяжёлый вариант вида убран полностью. Это заодно и есть ответ на п.4 («Гарантия» в блоке DBS должна выглядеть как в первом блоке) — раз компонент теперь один на все товары и обе услуги, расхождения по конструкции больше нет, различается только состав доступных услуг (у болта — только гарантия, у холодильника — установка и гарантия), не разметка.
Ради этого легаси-чип «Гарантия «72 часа»» (доработка 6, был сознательно оставлен только у болта) в этой правке всё-таки убран и там — держать одну и ту же гарантию в двух структурно разных представлениях на разных товарах стало прямо противоречить требованию «должно быть идентично». У болта теперь та же строка-с-флажком, тот же артикул warranty-premium, что и у холодильника.
Модель состояния обобщена с ключа «услуга» на составной ключ «услуга + к какому товару привязана». До этой правки setServiceActive()/удаление по факту дедуплицировали список только по itemId — это было незаметно, пока одна и та же услуга не могла одновременно относиться к двум разным товарам. Теперь, когда и холодильник, и болт предлагают «Гарантия Премиум», это стало реальной ситуацией: гарантия для холодильника и гарантия для болта — два независимых элемента заказа с одинаковым itemId, но разным linkedItemId. Все операции (проверка «активна ли», добавление, удаление) переведены на пару (itemId, linkedItemId) — исправлено в корзине (десктоп и моб.) и, отдельно, в карточке товара (десктоп и моб.), где та же дедупликация по одному itemId была бы тем же скрытым багом: включение гарантии на карточке холодильника стёрло бы гарантию, ранее привязанную к болту. Подтверждено через Playwright: гарантия к двум разным товарам одновременно — два отдельных элемента в состоянии, сумма считается верно (61 551 ₽ в тестовом сценарии), переключение одной не трогает другую.
2–3 (шильдик рассрочки «съезжает» к услуге; цена установки «похожа на холодильник») оказались одним и тем же CSS-багом, не двумя разными. .cart-item-side в общем компоненте задаёт justify-content: space-between, а .cart-item не переопределяет align-items (по умолчанию stretch) — пока строка была короткой, это было незаметно; как только строка товара выросла из-за вложенных строк услуг под ней, .cart-item-side растягивался на всю высоту и «раскидывал» своё содержимое (иконки/цена/шильдик рассрочки) по высоте — шильдик рассрочки холодильника оказывался визуально рядом с последней строкой услуги, а не с ценой холодильника. Прямая Playwright-проверка подтвердила: цена установки в DOM и так была верной (2 360 ₽) всё это время — «41 тысяча» была не багом расчёта, а зрительной иллюзией из-за смещённого шильдика. Исправлено одной строкой (.cart-item-side { justify-content: flex-start }) в десктопной корзине; в мобильной такая же строка уже была добавлена раньше.
На мобильной корзине при переходе на всегда-видимые строки услуг обнаружился отдельный, ранее скрытый баг вёрстки на узком экране (390px) — не то, о чём просил пользователь, но напрямую мешавшее выполнить п.1 («аккуратные строки»): у товара с длинным шильдиком рассрочки (холодильник) горизонтальное пространство настолько зажималось, что вложенные строки услуг схлопывались до нескольких пикселей ширины и текст названия наезжал на цену. Причина — тот же класс .installment-line без ограничения ширины предпочитал не переноситься (max-content), «съедая» почти всю строку на узком экране, а .cart-item-side с flex-shrink: 0 в базовом компоненте не уступал место. Для .cart-item.is-nested (вложенные строки услуг) вёрстка на мобильном переведена с флекса на CSS grid с именованными областями — чекбокс/название/цена больше не соревнуются за одну строку, цена уходит под название на новую строку внутри той же ячейки. Проверено визуально и через прямые замеры getBoundingClientRect() на нескольких промежуточных вариантах, пока наложение не исчезло полностью.
5. На чекауте гарантия по ошибке попадала в адресный блок «Установка техники» (требующий адрес/дату/время визита мастера) — потому что оба артикула-услуги имели один и тот же seller: 'services', а группировка по адресным блокам шла именно по seller. Гарантия визита мастера не требует. Решение: у каталожных записей появился отдельный признак isService: true (для «это услуга, не товар» — используется в подсчёте сумм и в мини-чеке), а seller у warranty-premium изменён на отдельное значение 'warranty', не входящее в перечень адресных блоков ['own', 'km-profil', 'services']; install-haier сохранил seller: 'services', так как визит мастера ему действительно нужен. Гарантия теперь видна только строкой «Гарантия» в мини-чеке справа. Заодно строки «Установка»/«Гарантия» в мини-чеке переведены с .find() на .filter().reduce() — раз услуга может встречаться по несколько раз (гарантия на холодильник и на болт одновременно), нужна сумма всех вхождений, а не первое найденное. Попутно убран весь легаси-код строки «Услуги (гарантия «72 часа»)» и связанного с ней ook696ServicesSelection — он читал чипы, которых с этой правки в корзине больше не существует ни у одного товара.
6. У карточки услуги убрано состояние «добавлена и привязана к товару». Раньше кнопка определяла «услуга уже в корзине» по одному itemId, без учёта linkedItemId — то есть если гарантия была добавлена через виджет на карточке холодильника, карточка услуги ошибочно считала себя «уже добавленной» и показывала, к какому товару услуга привязана. По требованию — это должны быть как бы две разные услуги: карточка услуги теперь ищет только запись с linkedItemId: null (свою, непривязанную), полностью игнорируя привязанные. При этом у самого добавления был реальный скрытый баг: фильтр очистки перед добавлением новой записи (filter(s => s.itemId !== SERVICE_ID)) удалил бы и привязанную запись тоже — исправлено на составной ключ, удаляется/заменяется только прежняя непривязанная запись. Проверено через Playwright: гарантия, привязанная к холодильнику, и гарантия, добавленная с карточки услуги, сосуществуют как два отдельных элемента списка одновременно, ни один клик на карточке услуги не трогает привязанную запись.
Проверено через Playwright на всех восьми файлах задачи (карточка товара, карточка услуги, корзина, чекаут — десктоп и моб.): без ошибок в консоли; строки услуг всегда видны и компактны без наложения текста на всех проверенных ширинах; шильдик рассрочки — рядом с ценой товара; гарантия визуально идентична в обоих блоках продавцов; чекаут не показывает гарантию в адресном блоке установки ни при одном, ни при двух одновременных вхождениях услуги; суммы в мини-чеке и общем итоге сходятся во всех сценариях, включая одновременную гарантию на два разных товара.
По просьбе перепроверить прототипы на соответствие последним требованиям — все 6 пунктов доработки 2 пройдены заново сквозными сценариями (реальные клики по чекбоксам/кнопкам/ссылкам, переход из корзины на чекаут и из карточки товара на карточку услуги по настоящим кнопкам и ссылкам, а не прямая запись в localStorage), на десктопе и мобильной версии. Все 6 пунктов подтверждены. Заодно найдены 2 реальных бага, не пойманных проверкой из доработки 2 — там сценарий с двумя одновременными непривязанными услугами не тестировался, ловятся оба только когда в блоке «Услуги» корзины остаётся ровно один из двух зарезервированных слотов.
Баг 1 (повтор уже известного в проекте паттерна): пустой второй слот блока «Услуги» был виден. Слот помечен атрибутом hidden, но общий класс .cart-item { display: flex } перебивает браузерное правило [hidden]{display:none} — авторские стили всегда сильнее правил браузера по умолчанию, независимо от специфичности. В результате при ровно одной непривязанной услуге второй слот отображался пустой рамкой с включённым чекбоксом. Исправлено явным .cart-item[hidden]{display:none} в обоих файлах корзины (десктоп и моб.).
Баг 2 (новый): иконка в слоте не зависела от того, какая услуга в нём оказалась. Иконки обоих слотов были жёстко зашиты в разметке (слот 0 — гаечный ключ установки, слот 1 — щит гарантии); JS-рендер обновлял текст/цену/чекбокс, но не иконку. При единственной непривязанной гарантии (которая попадает в первый свободный слот) показывалась иконка установки. Исправлено — иконка теперь берётся из каталога услуг по фактическому артикулу и подставляется при каждом рендере.
Проверено повторно после обеих правок: пустой слот полностью невидим (а не просто визуально пустая рамка), иконка верно соответствует услуге в любом из двух слотов, на обеих платформах.
Пользователь нашёл в живом использовании 4 новых дефекта, все — в корзине и на чекауте.
1. При увеличении количества товара цена рядом с привязанной к нему услугой перезаписывалась ценой товара. Причина — в JS-функции пересчёта цены строки (updateItemLinePrice) использовался item.querySelector('.cart-item-price') без ограничения поддерева: раз строки услуг находятся в разметке РАНЬШЕ собственной цены товара, такой запрос находил первую попавшуюся цену — цену вложенной услуги — вместо цены самого товара, и перезаписывал именно её. Исправлено ограничением поиска через :scope > — теперь функция берёт цену/чекбокс/количество строго у прямых потомков строки товара, не заходя во вложенные строки услуг.
2. У отдельно добавленной услуги (не привязанной к товару, из группы «Услуги» внизу корзины) не было переключателя количества вообще — в отличие от обычного товара. Добавлен тот же степпер количества, что у товаров; цена и передача количества на чекаут работают по той же схеме. Так как один и тот же слот при перерисовке может достаться другой услуге, количество сбрасывается в 1 только при смене услуги в слоте, а не при каждом обновлении.
3. На чекауте в блоке «Установка техники» строка адреса называлась «Адрес доставки» — неточно, установку никуда не доставляют, мастер приезжает оказать услугу по адресу. Переименовано в «Адрес оказания услуги» — только в этом блоке, у блоков реальной доставки (Холодильник.Ру, DBS-продавцы) подпись не менялась.
4. На мобильной корзине название вложенной в товар услуги переносилось на 3+ строки (иногда по слогам) — узкой была не сама строка услуги, а колонка, которую ей оставляла верстка: блок вложенных строк услуг жил внутри .cart-item-body товара и делил горизонтальное место с соседней колонкой цены/бейджа рассрочки этого же товара, а тем всегда не хватало ширины на узком экране. Решение — блок строк услуг вынесен из .cart-item-body наружу, стал прямым потомком строки товара и получил flex-basis: 100% при flex-wrap: wrap у родителя — теперь он всегда переносится на свою собственную строку на всю ширину карточки, не деля место с колонкой цены товара. Название на всех проверенных случаях умещается в одну строку.
Проверено через Playwright на десктопе и мобильной версии: увеличение количества товара больше не трогает цену услуг; количество отдельной услуги меняется, множится верно и корректно долетает до чекаута (проверено сквозным переходом «Перейти к оформлению»); подпись «Адрес оказания услуги» на чекауте в обоих файлах; название вложенной услуги на мобильной корзине — в одну строку с запасом по ширине; каскадное удаление товара по-прежнему корректно убирает вынесенный блок его услуг вместе с самим товаром — без ошибок в консоли.
1. После выноса блока строк услуг на всю ширину карточки (доработка 4, п.4) пропала визуальная связь с товаром — строки услуг выглядели как самостоятельный раздел, а не как часть конкретного товара. Сделан компромисс между старой версткой (строки услуг были вложены внутрь тела товара — связь была наглядной, но колонка была слишком узкой) и версией без отступа (широко, но не читалось, что услуги относятся к этому товару): добавлен отступ слева (64px, вместо прежних ~130px) и тонкая вертикальная линия-«ветка» рядом со строками услуг — читается как «эти пункты относятся к товару выше», при этом заголовку услуги по-прежнему хватает ширины на одну строку.
2. Новая логика: количество привязанной к товару услуги растёт вместе с количеством товара. Раньше у привязанной услуги количество всегда было 1 независимо от количества товара (своего переключателя количества у неё нет и не появилось — она относится к товару целиком, не покупается отдельными штуками). Степпер количества товара теперь при каждом изменении обновляет и цену, и «эффективное количество» каждой привязанной к этому товару услуги: 2 холодильника — 2 установки и 2 гарантии, с соответствующей ценой. Реализовано без изменения формата состояния — количество услуги, как и раньше у товаров, не хранится отдельно, а считывается «на лету» из степпера товара в момент любого пересчёта (в том числе при переходе на чекаут).
Проверено через Playwright на десктопе и мобильной версии: заголовок вложенной услуги — в одну строку, отступ и линия визуально связывают её с товаром выше, у обоих продавцов одинаково; увеличение количества товара до/после включения услуги — цена услуги пересчитывается верно в обоих случаях (было ли количество увеличено до или после включения услуги); уменьшение количества обратно возвращает цену услуги к исходной; сумма в мини-чеке и чекаут (включая чип с «×N» в адресном блоке услуги) считают верно; каскадное удаление и выбор «Все товары» не задеты правкой — без ошибок в консоли.
Пользователь прислал скриншоты реального сайта для шагов 2–4 воронки чекаута (после шага 1, уже покрытого прототипами OOK-836) и попросил собрать as-is по ним, затем to-be по образцу остальных экранов задачи. Скриншоты были высокими (до 4503px) — перед чтением нарезаны локальным инструментом tools/slice_screenshot.py на части по 1400px (база знаний, правило 6).
Шаг 2 — «Подтверждение заказа», новый экран. As-is (ook-836-checkout-confirm-asis.html) — read-only сводка выбранного на шаге 1: способ получения, дата, способ оплаты, «Перейти к оплате». To-be (ook-836-checkout-confirm-tobe.html) читает реальный выбор из корзины (ook696CartSelection) и группирует его в те же независимые блоки, что и сам чекаут (Холодильник.Ру / DBS-продавец / Установка техники) — каждый блок подтверждается отдельной карточкой. Кнопка «Далее» на чекауте (ook-836-checkout-tobe.html/моб.), которая раньше никуда не вела, теперь ведёт сюда.
Шаг 3 — переход к оплате, обобщённая заглушка (не as-is/to-be пара). Реальный шаг — переход на страницу стороннего платёжного провайдера (в присланном скриншоте — интерфейс СберБанка). Осознанное решение — не воспроизводить брендированный интерфейс чужого продукта: собрана нейтральная заглушка (ook-836-payment-redirect.html) на компонентах самого прототипа, с суммой заказа и кнопкой «Симулировать успешную оплату» для прохода демо-пути до конца. Зафиксирован факт (не отдельный прототип): к этому шагу заказ уже создан в системе со статусом «не оплачен» и доступен для повторной оплаты из личного кабинета — личный кабинет по прямому указанию пользователя не прорабатывается.
Шаг 4 — «Спасибо за заказ» (TYP), заполнена пустая заглушка, оставленная в самой первой версии задачи (2026-07-29) в ожидании реального референса. As-is (ook-836-typ-asis.html) собран по скриншоту один в один: статус-шаги заказа, способ получения/дата, информация об оплате, оценка удобства оформления, промо-баннер «Получайте подарки». To-be (ook-836-typ-tobe.html) отвечает на открытый вопрос, оставленный в исходной заглушке (п.9 требований): читает общее состояние услуг ook836ServiceState и показывает одно из двух состояний — если услуги в заказе нет, блок допродажи (установка/гарантия к уже купленному холодильнику); если услуга есть — статус каждой купленной услуги («мастер свяжется для согласования визита» и т.п.) вместо повторного предложения купить то, что уже куплено.
Проверено через Playwright сквозным сценарием на обеих платформах: карточка товара (включить услуги) → корзина → чекаут → «Далее» → подтверждение заказа (верно сгруппированные блоки, верные суммы) → «Перейти к оплате» → заглушка оплаты (та же сумма) → «Симулировать оплату» → TYP (корректно показывает купленные услуги и их статус, суммы сходятся на каждом шаге) — без единой ошибки в консоли на всех восьми новых файлах. Старая пустая заглушка ook-836-typ.html удалена, ссылки на index.html обновлены.
По прямому запросу опробован новый подход к презентации прототипов: обычный to-be рассчитан на то, что его показывает и комментирует автор (часть ссылок ведёт в никуда, нужный путь неочевиден постороннему), а для самостоятельного прохождения без сопровождения нужен один прямой путь с минимумом развилок и подсказкой, куда можно нажимать. Опробовано на полной воронке OOK-836 (задокументировано как новое общее правило — база знаний, Правило 11, раздел «Подход к созданию прототипов»).
Собран общий переиспользуемый механизм — components/guided-flow.js + стили в components.css: элементы, которые реально продолжают сценарий на экране, помечаются атрибутом data-flow-hotspot; клик/тап мимо них на секунду подсвечивает все помеченные элементы пульсирующей обводкой. Разметка не покрывает страницу целиком — шапка, футер, карусели и прочие декоративные href="#" остаются непомеченными, иначе подсказка теряет смысл (проверено: на карточке услуги 2 хотспота, на остальных экранах — по 1–2).
Сценарий: старт на карточке услуги «Установка встроенного холодильника» (услуга ещё не в корзине) — ook-836-service-card-tobe.html/-mobile-tobe.html. Дальше: корзина (можно включить/выключить ту же услугу нового — вложенным флажком под товаром) → чекаут → подтверждение заказа → оплата (заглушка, доработка 6) → «Спасибо за заказ» — без сопровождающих пояснений, только сама последовательность экранов.
Попутно найден и исправлен реальный пробел в UX мобильной карточки услуги (не только в демо-разметке): единственная кнопка «В корзину» вела дальше только после того, как услугу уже добавили («В корзине — перейти →»); если пользователь решал не добавлять услугу, продолжить путь на мобильной версии было физически некуда (на десктопе для этого служит иконка корзины в шапке, но на мобильной версии полной шапки нет). Добавлена всегда видимая ссылка «Перейти в корзину без услуги →».
Проверено через Playwright реальными кликами (не подстановкой в localStorage) на обеих платформах: подсветка появляется по клику мимо хотспотов и гаснет через ~0.9 с; полный путь пройден дважды — на десктопе с добавлением услуги на обоих шагах (карточка + корзина), на мобильной версии с пропуском на карточке услуги через новую ссылку и добавлением только в корзине — оба прогона без единой ошибки в консоли, суммы на «Спасибо за заказ» сходятся. Показ одной и той же услуги дважды на TYP при намеренном добавлении на обоих шагах — не баг, а задокументированное поведение архитектуры (см. требования OOK-836, п. «уточнение к п.1/2»): привязанный к товару и непривязанный экземпляры услуги — независимые позиции заказа.
Правка после показа: новая метка «▶ Пройти сценарий целиком» на index.html изначально была слишком длинной (с пояснением в скобках) и не переносилась по словам — не помещаясь по ширине, растягивала всю колонку To be и ломала выравнивание обеих колонок карточки задачи. Исправлено: текст метки сокращён, плюс на будущее в .proto-action-label добавлены max-width и перенос строк — чтобы длинная метка в любой будущей задаче переносилась, а не раздвигала колонку.
По итогу показа доработки 7 — запрос собрать что-то вроде «конфига прототипа»: для базового прохождения сценария DBS-товар в корзине не нужен и только отвлекает, но терять сценарий с DBS (демонстрирует дробление корзины) тоже не хочется. Решение — два именованных пресета, выбираемых параметром ?scenario= прямо в стартовой ссылке сценария.
Стартовый файл сценария (ook-836-service-card-tobe.html/-mobile-tobe.html), самым первым, до остальной логики страницы: если ?scenario= равен simple или full, один раз перезаписывает localStorage['ook696CartSelection'] нужным набором товаров и на всякий случай очищает ook836ServiceState (оба пресета должны стартовать без добавленных услуг, даже если в браузере осталось состояние от прошлого прохождения).
Обнаружилось, что этого недостаточно: ook696CartSelection — это то, что корзина записывает при переходе к оформлению, а не то, что она читает при отображении своего собственного списка товаров (оба товара в разметке корзины всегда присутствуют статически, чекбоксы только включают/выключают их в оформление). Поэтому пресет «без DBS» не убирал DBS-товар с самого экрана корзины — только из корзины/чекаута, если открыть их напрямую. Добавлена вторая, разовая метка ook836DemoScenario: корзина (ook-836-cart-tobe.html/-mobile-tobe.html) читает её при загрузке и, если сценарий «simple», прячет весь блок DBS-продавца (.seller-group[hidden]) — тем же способом, что уже используется при обычном удалении товара пользователем, поэтому счётчики и суммы (getActiveCheckboxes уже учитывает видимость) пересчитываются корректно без отдельной правки. Метка стирается сразу после чтения — обычный прямой заход в корзину (без повторного старта со сценарной ссылки) снова показывает оба товара, как раньше.
Пресет «Один товар» — только свой товар (fridge), без DBS. Пресет «Товар + DBS» — тот же товар плюс DBS-товар (bolt), для сценария с дроблением корзины на независимые блоки. На index.html — две отдельные ссылки вместо одной «▶ Пройти сценарий целиком». Проверено через Playwright на обеих платформах: пресет «simple» — DBS скрыт и в корзине, и в чекауте, суммы и счётчик товаров пересчитаны верно (1 из 1); пресет «full» — оба товара на месте (2 из 2); повторный прямой заход в корзину после прохождения сценария возвращает оба товара — без ошибок в консоли.
1. Даты/время доставки на мобильном чекауте — в одну горизонтальную свайпаемую строку. Раньше чипы переносились на несколько строк (flex-wrap: wrap), занимая много места по вертикали. В components.css добавлен опциональный модификатор .date-chip-row.is-scroll/.time-chip-row.is-scroll (flex-wrap: nowrap; overflow-x: auto) — опциональный, чтобы не задеть остальные задачи (OOK-275, OOK-696), которые используют тот же общий компонент чипов, но не подключали модификатор. Подключён только в ook-836-checkout-mobile-tobe.html, на всех пяти строках дат/времени (блоки «Холодильник.Ру», «КМ-Профиль», «Установка техники»).
2. Ссылка «Перейти в корзину без услуги →» на карточке услуги (моб.) заменена на нижний таббар — как на реальном сайте. Прежняя ссылка воспринималась как часть демо-разметки, а не элемент интерфейса. Добавлен переиспользуемый компонент .mobile-tabbar (6 пунктов: Меню / Каталог / Избранное / Поиск / Корзина / Павел — по образцу реального сайта) в components.css, подключён во все браузинговые экраны задачи: ook-836-product-card-mobile-asis.html (у экрана он тоже отсутствовал — реальный пробел в as-is, а не только in-scope правка), ook-836-product-card-mobile-tobe.html (синхронизировано с as-is) и ook-836-service-card-mobile-tobe.html. Пункт «Корзина» в последнем — обычная ссылка на корзину, помечена как хотспот демо-сценария (Правило 11) вместо прежней ссылки. Активный пункт таббара сознательно не проставлен ни на одном из экранов — карточка товара/услуги не соответствует напрямую ни одному из пяти разделов.
3. В корзине у строк услуг убран артикул (Артикул УСТ-247-ВСТР / Артикул ГАР-ПРЕМ-3Y) — не нужен пользователю, занимал место. Убрано у всех строк услуг (вложенных и в отдельной группе «Услуги») на десктопе и мобильной версии, включая JS-шаблон, которым заполняется слот отдельной группы.
4. Кнопка «Удалить» у товаров в мобильной корзине — исправлена реальная ошибка. Вместо иконки корзины/удаления на мобильной версии отображались три вертикальные точки (перепутанная иконка — скопирована иконка меню вместо иконки удаления, видимо, при более ранней адаптации вёрстки под мобильный экран). Заменено на ту же иконку урны, что и на десктопе, на всех четырёх кнопках удаления (товар «Холодильник.Ру», DBS-товар, обе строки отдельной группы «Услуги»). Заодно найден и исправлен второй, более старый баг того же места — кнопка удаления DBS-товара («КМ-Профиль») никогда не была подключена к обработчику ни на десктопе, ни на мобильной версии (не было ни id, ни вызова wireCascadeDelete) — визуально кликабельна, физически ничего не делала. Подключена на обеих платформах: wireCascadeDelete('delete-bolt', 'bolt').
Проверено через Playwright на обеих платформах: чипы дат/времени — в одну строку, реально скроллятся вбок (scrollWidth > clientWidth); клик по «Корзина» в таббаре карточки услуги без добавления услуги — переход в корзину, полный сценарий пройден до конца без ошибок; «Артикул» нигде не отображается; кнопка удаления DBS-товара реально убирает его из корзины и на десктопе, и на мобильной версии — без ошибок в консоли.
По итогу доработки 9 — на пункте «Корзина» нужен реальный счётчик, не просто иконка. Добавлен .mobile-tabbar-badge (тот же компонент, что уже использовался у «Избранное», раньше — статичная демо-цифра) на ook-836-product-card-mobile-tobe.html и ook-836-service-card-mobile-tobe.html: сумма товаров (ook696CartSelection, тот же дефолт-заглушка 2, что и на остальных экранах OOK-836, если ничего ещё не выбрано) и активных услуг (ook836ServiceState.length) — то же определение «количества товаров», что уже используют корзина и чекаут. Пересчитывается сразу при изменении состояния на самой странице (тумблеры на карточке товара, кнопка «В корзину» на карточке услуги), без перезагрузки.
На as-is (ook-836-product-card-mobile-asis.html) индикатор сознательно не добавлен — на реальном скриншоте-референсе (страница поиска/каталога) бейджа на «Корзина» не было, а моделировать реальное состояние аккаунта не задача as-is-экрана.
Проверено через Playwright: дефолт (ничего не выбрано) — бейдж «2» на обеих страницах; включение тумблера «Установка» на карточке товара — бейдж «3» сразу, без перезагрузки; клик «В корзину» на карточке услуги — бейдж «3» сразу; сценарий ?scenario=simple — бейдж «1» (только свой товар, без DBS), корректно отражает реально сиженное состояние — без ошибок в консоли.
По прямому запросу — сверка задачи с правилами 1–11 и исправление найденных нарушений. Разобрано подробно в отдельном разговоре с пользователем; здесь — сводка правок.
Правило 8 (открытые вопросы — всегда <ol>): в требованиях к задаче раздел «Открытые вопросы» был <ul> — исправлено на <ol>.
Правило 4 (требования — без дат, история — в «Историю разработки»): из требований убраны пять датированных <h3> (гарантия как вторая услуга, добавление из корзины, пересборка карточки услуги, «два независимых элемента заказа», гарантия без адресного блока) — эти факты уже задокументированы здесь, в истории. Актуальные на сегодня бизнес-факты из них перенесены без дат в соответствующие пункты «Детальных требований» (п.1, п.2, п.6) и в «Описание решения» (оговорка про гарантию как демонстрацию паттерна, не подтверждённый скоуп).
Правило 7 (без ссылок на другие задачи вне «Открытых вопросов»): в п.4 требований убрана ссылка на OOK-696 (базы знаний раздел 11) — оставлен только сам факт («оформление создаёт несколько независимых заказов»), без внешней привязки. Гораздо больше нарушений было в комментариях внутри прототипов — ook-836-cart-tobe.html и ook-836-checkout-tobe.html (десктоп и моб.) почти целиком пересказывали унаследованную логику и историю OOK-696 (блоки по продавцу, Яндекс-Сплит-исключение, самовывоз DBS, адресная независимость блоков, найденные в OOK-696 баги) вместо того чтобы просто сослаться на модалку OOK-696 и описать только собственную дельту OOK-836. Оба файла (и мобильные версии) радикально сокращены — оставлено только то, что реально добавляет OOK-836: блок «Установка техники», исключение услуг по способу оплаты, отдельные строки «Установка»/«Гарантия» в сводке, упрощённые демо-данные. Заодно это исправило и скрытое нарушение правила 2 (to-be-модалка не должна дублировать унаследованные требования) — обе модалки фактически предметом являлись пересказом требований OOK-696, а не только своей дельты.
Правило 9 (без технических имён — бизнес-язык вместо кода): по итогам обсуждения с пользователем — убраны все упоминания localStorage-ключей (ook836ServiceState, ook696CartSelection), полей состояния (linkedItemId, addedVia, itemId) и CSS-классов (.mobile-tabbar, .delivery-block-items) из требований и комментариев во всех файлах задачи. Заменены на бизнес-описание того же факта (например, «читают и пишут один и тот же список услуг» вместо ключа состояния) или на ссылку на видимый элемент интерфейса («кнопка «В корзину»» вместо id). Оставлены только по-настоящему видимые пользователю идентификаторы (артикулы УСТ-247-ВСТР/ГАР-ПРЕМ-3Y — реальные, показанные на странице) и параметры URL, которые нужны читателю операционно, чтобы воспользоваться демо-сценарием (?scenario=, ?service=) — без них нельзя было бы объяснить, какую ссылку отправить коллеге.
Проверено через Playwright: полный демо-сценарий (карточка услуги → корзина → чекаут → подтверждение → оплата → TYP) пройден заново на обеих платформах после всех правок — без ошибок в консоли; блоки доставки, кнопка «Далее», модалка требований (счётчик находок, нумерация вопросов) — всё работает как раньше.
OOK-834У holodilnik.ru уже есть бонусная программа и программа лояльности, но бонусы сейчас привязаны почти исключительно к заказам — пользователю негде получить бонус просто за лёгкое взаимодействие с сайтом вне покупки. Из-за этого нет простого, регулярного повода вернуться на сайт вечером, когда решение о покупке ещё не созрело.
Вечерний опрос — способ дать пользователю лёгкий, безрисковый повод провзаимодействовать с сайтом (один клик) и получить за это бонус, одновременно направляя его в каталог интересующей категории. Сами ответы на вопрос опроса не собираются и не анализируются — механика существует ради вовлечения, а не сбора данных.
Появляется новый раздел сайта — короткие «вечерние опросы». Каждый опрос — один вопрос с несколькими вариантами ответа в виде ссылок, без кнопки «Ответить»: клик по любому варианту сразу засчитывается как участие и ведёт на посадочную страницу с подборкой товаров по теме, а бонус начисляется отдельно.
Бонус за участие получают только участники программы лояльности. Если пользователь не авторизован или авторизован, но не в программе лояльности, — перед начислением бонуса ему нужно пройти вход по телефону и/или вступить в программу лояльности; для уже авторизованного участника программы лояльности всё происходит в один клик, без дополнительных экранов.
Об активных опросах пользователь узнаёт двумя способами: на самом сайте (отдельный раздел со списком опросов) и по email-рассылке — письмо не дублирует варианты ответа, а одной кнопкой ведёт на сайт, где и происходит участие.
Чтобы опросы могли появляться регулярно, бизнесу нужен инструмент для их самостоятельного создания — с указанием вопроса, вариантов ответа, срока действия и размера бонуса, без участия разработки в каждом конкретном опросе.
Нужна аналитика по каждому опросу: сколько пользователей его увидели (просмотры карточки в списке и/или страницы опроса) и сколько поучаствовали (клик по варианту ответа), с разбивкой по конкретным опросам. Точный состав метрик и способ сбора — на усмотрение дата-аналитика; предполагается, что аналитик либо составит по этому разделу своё отдельное ТЗ, либо настроит сбор самостоятельно.
Отдельная страница со списком всех опросов. У каждого опроса — статус (Активен / Вы уже участвовали / Опрос завершён), срок действия, вопрос и размер бонуса за участие. Клик по карточке открывает страницу опроса.
Список постраничный — по 20 опросов на страницу.
Вопрос и варианты ответа — в виде ссылок, без кнопки «Ответить»: клик по варианту сразу означает участие. Под вариантами — короткая подпись о том, что произойдёт после клика (начисление бонуса и переход на страницу с подборкой товаров по теме), чтобы переход не был неожиданностью.
У опроса три состояния: активен (можно ответить), уже отвечен (выбранный ранее вариант подсвечен, повторно бонус не начисляется), завершён (участие недоступно, варианты неактивны). Первый клик — финальный: изменить ответ или повторно поучаствовать в том же опросе нельзя. Завершённый опрос остаётся доступен по ссылке — вопрос и варианты можно посмотреть, просто нельзя ответить.
Важно для формулировок интерфейса: достоверно мы знаем только факт участия пользователя в опросе (что он уже отвечал), но не факт начисления бонуса — начисление происходит отдельно и не мгновенно (см. раздел 6). Интерфейс не должен утверждать «бонусы начислены» — только «вы уже участвовали»/«участие засчитано».
Клик по варианту ответа ведёт по одному из трёх путей, в зависимости от статуса пользователя:
Начисление бонуса за участие в опросе доступно только участникам программы лояльности — просто быть авторизованным пользователем недостаточно.
Вход происходит в модальном окне поверх текущей страницы (на мобильном — в шторке, выезжающей снизу экрана), без перехода на отдельную страницу. Вход только по номеру телефона, без пароля: пользователь вводит телефон, получает 4-значный код по SMS и вводит его — вход выполнен. Есть таймер повторной отправки кода и блок «Не приходит код авторизации?» со ссылкой на звонок в поддержку, чекбокс согласия на рекламные рассылки (по умолчанию отмечен) и ссылки на согласие по обработке персональных данных и пользовательское соглашение.
Отдельный шаг после авторизации (если пользователь ещё не участник программы лояльности) — короткий экран с объяснением, зачем это нужно, и кнопкой «Присоединиться к программе лояльности». Сама механика вступления (форма, условия и т.д.) здесь не проработана, показана только точка входа.
После успешного участия пользователь попадает на страницу с подборкой товаров по теме опроса. На странице явно и заметно показывается сообщение о начислении бонуса — в виде модального окна, которое открывается автоматически, чтобы его точно заметили.
Тот же опрос дублируется в email-рассылке — всегда в одном и том же виде, независимо от того, авторизован ли получатель на самом деле и состоит ли в программе лояльности: получатель письма считается уже авторизованным участником программы лояльности. Отдельного варианта письма для «гостя» нет и не нужно. В письме — вопрос и одна кнопка «Участвовать в опросе», которая ведёт на страницу опроса на сайте (в мобильную версию — расчёт на то, что письма чаще открывают с телефона). Кнопка в письме сознательно ведёт на сайт, а не начисляет бонус сразу по клику в самом письме — цель этой механики в целом не «пройденный опрос», а трафик на сайт.
Чтобы вечерние опросы вообще могли появляться на сайте, нужен отдельный раздел в админке для их создания и управления — прототип показывает только сторону пользователя (сайт, письмо), но не сторону того, кто эти опросы заводит и настраивает.
Минимально нужно уметь:
Отправка email-рассылки — сам процесс отправки нужно проработать отдельно. Рассылка отправляется через партнёра Mindbox — нужно выяснить, можно ли автоматизировать создание этих рассылок, или каждое письмо придётся готовить вручную.
Собрать требования по SEO.
https://drugtolik.ru/holodilnik/index.html?task=OOK-834
Прикрепить ссылку/задачу на макеты
OOK-834Внутренний журнал изменений по датам — не для дизайнера/аналитика, но полезен при дальнейших доработках, чтобы понимать, что и почему менялось. Актуальные требования — в соседнем документе «Требования к задаче».
Собраны первые прототипы по приложенной к задаче схеме (флоучарт от руки): листинг опросов, страница опроса с демо-переключателем персон (Гость / Авторизован без ПЛ / Авторизован с ПЛ), одно универсальное письмо, экран /usercp/loyalty/ (форма логин+пароль на отдельной странице — позже пересмотрено по реальным скриншотам), обобщённая посадочная страница с баннером начисления бонуса.
Посадочная страница пересобрана по реальным скриншотам категории «Двухкамерные холодильники» (десктоп и мобильная версии — отдельными файлами): шапка с поиском, хлебные крошки, фильтры, карточки товаров, пагинация, подборки, футер. Персона по умолчанию на странице опроса изменена с «Гость» на «Авторизован и в ПЛ» — чтобы первый клик сразу показывал самый простой сценарий. Письмо разделено на два файла для двух крайних сценариев получателя (авторизован+ПЛ / гость).
Ссылки в обоих письмах перенаправлены на мобильные версии страниц вместо десктопных. Для этого впервые появилась мобильная версия экрана /usercp/loyalty/. Расширенная шапка (с поиском), хлебные крошки и подвал добавлены также на листинг опросов и страницу опроса (раньше были только на посадочной странице). Сообщение о начислении бонуса переделано из закрываемого баннера в модальное окно, открывающееся автоматически при загрузке страницы.
В обоих письмах варианты ответа заменены на одну кнопку «Участвовать в опросе», ведущую на мобильную страницу опроса — собственно участие (клик по варианту, начисление бонуса) теперь происходит только на сайте, а не в письме.
По приложенным скриншотам реальной формы входа на holodilnik.ru экран авторизации полностью пересобран: вместо формы «логин/email + пароль» на отдельной странице — модальное окно (на мобильном — шторка снизу) с входом по телефону и SMS-кодом, без пароля. Модалка открывается прямо на странице опроса по клику на вариант ответа, а не уводит на отдельную страницу. Отдельные файлы экрана /usercp/loyalty/ сохранены как самостоятельные демо-страницы (доступны по прямой ссылке с index.html) — на них та же модалка открывается автоматически.
Задаче присвоен официальный номер OOK-834 (был плейсхолдер OOK-XXX) — переименованы все файлы прототипов и обновлены все ссылки. Документация задачи разделена на три уровня: «Требования к задаче» (для дизайнера/аналитика, без дат и техно-подробностей), «История разработки прототипа» (этот журнал) и комментарии внутри каждого отдельного прототипа (только специфичные для конкретного экрана детали, не дублирующие общие требования).
Продакт-менеджер прошёлся по списку открытых вопросов из «Требований к задаче» и закрыл большинство из них:
ook-834-email-guest.html удалён, ook-834-email-loyalty.html переименован в ook-834-email.html и остался единственным вариантом. На index.html — одна кнопка «Открыть письмо» вместо двух («Участник ПЛ» / «Гость»).В требованиях не было ни слова о том, как эти опросы вообще появляются на сайте — весь прототип описывает только пользовательскую сторону. Добавлен раздел 8 «Инструмент управления опросами (админка)»: что нужно уметь как минимум (создание опроса с вопросом/вариантами/целями ответов, срок действия, размер бонуса, публикация/черновик/досрочное завершение, планирование заранее), и отдельно — потенциальные потребности бизнеса, которые прямо из прототипа не следуют, но логично возникают (несколько одновременно активных опросов и их порядок, базовая статистика по участию, связь публикации с рассылкой письма, клонирование опроса как шаблона). Раздел собран по тому, что видно в прототипе (статусы, срок действия, бонус за опрос), плюс типовые потребности похожих админ-инструментов.
Также в открытые вопросы добавлен пункт про сценарий для пользователя с установленным мобильным приложением ХОЛОДИЛЬНИК.РУ — по просьбе пользователя, без проработки, обсуждение отложено на потом.
Продакт-менеджер закрыл вопросы из блока «Потенциальные потребности бизнеса» раздела 8:
Обсудили сценарий пользователя с установленным мобильным приложением (нативным, кроме корзины — вебвью, см. базу знаний, раздел 16). Цель бизнеса — реализовать вечерние опросы и на сайте, и в приложении, но по возможности разнести доработку по времени, начав с сайта. Технический риск в переходный период — это перехват ссылок на уровне ОС (Universal Links на iOS, App Links на Android): если раздел опросов (или домен целиком) зарегистрирован за приложением, переход по ссылке из письма на телефоне с приложением откроет не сайт, а приложение, и дальше всё зависит от того, что приложение делает с незнакомым путём (открывает вебвью того же URL — тогда всё работает, или падает в ошибку — тогда флоу ломается). Открытый вопрос в требованиях переформулирован в два конкретных технических пункта для проверки с мобильной командой, вместо общей формулировки «как это будет выглядеть».
По запросу продакт-менеджера прототипы и требования проанализированы «со стороны PM» и «со стороны аналитика разработки» на предмет пробелов. Из всего списка находок разобрали и закрыли следующее:
ook-834-surveys-list.html/-mobile, ook-834-survey.html/-mobile) — состояние «уже участвовали» утверждало «бонусы начислены» / «бонусы уже начислены», хотя достоверно системе известен только факт участия, а не факт зачисления бонуса (оно происходит отдельно и не мгновенно — раздел 6). Текст заменён на «Участие засчитано» / «Вы уже участвовали в этом опросе» без утверждения про начисление. В требования (раздел 2) добавлено явное правило для будущих формулировок интерфейса.ook-834-surveys-list.html/-mobile) добавлена некликабельная пагинация внизу списка — сами 20 карточек заводить не стали, это только визуальная демонстрация наличия пагинации.Установлено общее правило оформления документа «Требования к задаче» для всех будущих задач — 5 обязательных разделов в фиксированном порядке: «Исходная задача» (1–2 абзаца, в чём проблема и почему решили её делать), «Описание решения» (максимум 4–5 абзацев даже для сложных задач — что хотим сделать и что меняется в продукте), «Платформы» (десктоп / мобильная версия сайта / планшет / мобильное приложение — по умолчанию все четыре, но по факту задачи), «Метрики» (нужно ли что-то мониторить — по сути требования к дата-аналитику) и «Детальные требования» (всё остальное, с подразделами). Правило записано в базу знаний как «Правило 5» (раздел «Подход к созданию прототипов»).
Документ OOK-834 переструктурирован под этот шаблон: добавлены новые разделы «Исходная задача» (собран из ранее не сформулированной явно бизнес-мотивации), «Описание решения» (4 абзаца, собраны из уже существовавших разделов 1–3, 7–8 в сжатом виде), «Платформы» (десктоп и мобильная версия сайта — проработаны; планшет — не прорабатывался, вопрос дизайнеру; email — отдельный канал; мобильное приложение — в перспективе, не в этом релизе) и «Метрики» (перенесено и расширено из абзаца «Аналитика кликов и просмотров», который раньше был спрятан внутри раздела про админку). Уровень заголовков поправлен: пять основных раздела — <h2>, а прежние разделы 1–8 плюс «Открытые вопросы» и «Что осознанно не проработано» — стали подразделами «Детальных требований» на уровень ниже, <h3>.
Мобильное приложение включено в скоуп задачи. В разделе «Платформы» формулировка «предполагается в перспективе, но не в этом релизе» заменена на «включено в эту задачу»; при этом сохранён открытый вопрос про возможность разнести доработку сайта и приложения по времени (сайт — отдельным этапом вперёд) — с уточнением про Universal Links/App Links и риском для перехода по ссылке из письма у пользователей с установленным приложением.
Добавлен раздел «9. SEO» в «Детальные требования» — пока заглушка с пометкой «Собрать требования по SEO.» (класс .todo-note, красный текст).
Добавлен новый обязательный 6-й раздел «Макеты» — и в саму задачу OOK-834 (ссылка на прототип задачи https://drugtolik.ru/holodilnik/index.html?task=OOK-834 + заглушка красным «Прикрепить ссылку/задачу на макеты» под будущую ссылку на макеты дизайнера), и в общее правило — «Правило 5» в базе знаний переименовано в «6 обязательных разделов». Для заглушек введён общий CSS-класс .todo-note (components.css, красный жирный текст через var(--color-danger)) вместо инлайновых стилей.
Ссылка «🕘 История разработки прототипа» убрана из карточки задачи — по прямому указанию: эти данные должны оставаться только для внутреннего использования между сессиями и не показываться другим пользователям сайта. Сам <template id="ook-834-history"> (этот файл) не удалён и продолжает пополняться — просто без видимой ссылки-триггера в .proto-card-docs. Это же изменение внесено в общий шаблон для будущих задач и в «Правило 4» базы знаний как durable-конвенция.
Карточка «Референс: главная страница» убрана из раздела «Общее» — по указанию «нам не нужна эта страница». Убрана только карточка/ссылка; сам файл prototypes/reference-homepage.html на диске сохранён, не удалён.