Files
houseplan-card/legacy/specs/212-device-icons-polish.md
Claudeandclaude[bot] df46fd1c3e docs(hygiene): ТЗ выпущенных задач без живых ссылок — в legacy/specs (#682)
Волна 5 эпика #674, перенос ТЗ (класс C). Из 240 файлов `docs/specs/` в
`legacy/specs/` уехали 219: на них не ссылается ни один живой файл (код,
тесты, скрипты, workflow, документы вне архива и ревью). Остались 21 ТЗ —
на которые ссылаются код, ADR, ISOMETRIC, SUN, RADAR, LIGHT (`docs/specs/067`),
DECOR-EDITOR, support-relay, и те, на которые ссылаются они сами; README
каталога объясняет, где искать остальное. Открытых issue с файлом ТЗ среди
перенесённых нет. Относительные ссылки перенесённых файлов переписаны
(`../X` → `../../docs/X`, соседние оставшиеся ТЗ → `../../docs/specs/…`) —
все 26 резолвятся. Попутно: битая ссылка в
`089-isometric-view-stage1.md:8` на удалённый `089-isometric-view.md` —
теперь команда `git show` по истории. Строка в `legacy/README.md`.

Issue: #682
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-09-27 22:10:46 +00:00

35 KiB
Raw Permalink Blame History

Issue #212 — размер, форма, нажатие и touch-hover маркеров устройств

  • Issue: https://github.com/Matysh/houseplan-card/issues/212
  • Связанные issue, реализуемые целиком здесь: #22, #154, #181
  • Приоритет: P1
  • Тип: bug/feature/polish, обычный трек
  • Пользовательское изменение: да
  • Touch editor: best effort / intentionally degraded

1. Сценарий

Домочадец смотрит план с телефона, настенной панели либо компьютера и нажимает на устройство. Маркер должен занимать меньше места, точно показывать длинное значение, сразу подтверждать принятую команду и не оставаться визуально «наведённым» после tap. Администратор видит ту же геометрию в редакторе устройств и его preview, не теряя сохранённую позицию или настроенный размер.

2. Что человек увидит до и после

До изменения новые маркеры выглядят крупнее требуемого, длинное значение имеет эллиптическую внутреннюю плашку, команда может не дать немедленного ответа, а touch иногда оставляет hover. После изменения маркер на 10% компактнее, внутренняя и внешняя капсулы эквидистантны, выполненное действие даёт короткий мягкий отклик, а hover существует только у настоящей мыши.

3. Проблема и подтверждённая причина

Аудит текущего dev подтвердил четыре независимых дефекта/пробела, которые по решению владельца выпускаются одной задачей:

  1. Общий renderer использует --dev-size как диаметр icon core и строит shell размером 1.26875 × core. После перехода на пакет #179 итоговый marker footprint стал визуально слишком крупным; отдельной общей коррекции 0,9 нет.
  2. display: value расширяет .device-core по тексту, но оставляет border-radius: 50%. Для широкого прямоугольника это эллипс. Внешний shell использует постоянный радиус, равный половине своей высоты, поэтому зазор между двумя формами меняется по дуге; это видно на скриншоте #212.
  3. _clickDevice() выполняет action либо открывает surface, но не создаёт отдельного transient feedback между принятием input и новым HA state.
  4. _notePointer() только навсегда защёлкивает статический _touchSeen и закрывает _tip. _hoverRoom продолжает устанавливаться из mouse events, View/shared CSS содержит негейтированные :hover, а настоящий mouse после touch не может вернуть hover без reload. Это подтверждает #154.

#181 также подтверждён: каноническое описание View hover находится в docs/UX-MODES.md, а не в docs/CANVAS.md.

4. Нормативные источники и приоритет

При расхождении требования применяются в таком порядке:

  1. тело #212 и прямое решение владельца выполнить здесь весь scope #22/#154/#181;
  2. это ТЗ после зелёного SPEC-REVIEW;
  3. дизайн-пакет #179 версии 1.1.1 и принятые уточнения #211;
  4. docs/SCOPE.md, docs/TOUCH-SUPPORT.md, docs/UX-MODES.md и docs/USER-GUIDE.ru.md;
  5. текущая реализация как compatibility baseline.

Числа #212 новее старого ТЗ #22 и имеют приоритет: минимальный scale равен 0.95, а полный цикл длится 200 ms. Остальной принятый продуктовый контракт #22 перенесён в §§9–11 и не требует чтения незамерженной ветки той задачи.

5. Scope

В задачу входят:

  • уменьшение полной визуальной геометрии каждого device marker на 10% поверх действующих global/per-device размеров;
  • общий renderer full View/kiosk, Device preview и houseplan-space-card;
  • исправление формы основного display: value;
  • click/tap/keyboard feedback только реально исполняемых marker actions;
  • confirmation, rapid repeat, reduced-motion и lifecycle feedback;
  • единый instance-local pointer-modality contract для full card и эквивалентный локальный contract для интерактивной кнопки static card;
  • room/device/opening/vacuum/header/dialog/shared-control hover в View;
  • touch, pen, desktop mouse и hybrid touch → mouse;
  • обновление канонических пользовательских/UX/testing документов;
  • unit, source-contract, browser smoke, golden и performance evidence.

6. Не входит в задачу

  • изменение дизайн-пакета, цветов, state priority, glyph viewport, pulse geometry, LQI thresholds или lock security;
  • изменение сохранённых icon_size, marker size, angle, layout coordinates либо автоматическая migration конфигурации;
  • optimistic смена HA state, icon, semantic color или aria-pressed;
  • feedback для info/more-info, открытия редактора, ссылки, no-op, secure, unavailable/missing target либо отменённого жеста;
  • новый пользовательский toggle интенсивности/длительности feedback;
  • новая поддержка touch-редакторов сверх действующего safety floor;
  • реализация room click-to-fit #152;
  • закрытие #22, #154, #181 или #212 исполнителем;
  • принятие golden baseline на Windows либо выпуск beta без команды владельца.

7. Уменьшение визуального размера на 10%

7.1. Формула

Пусть действующий размер до #212 равен:

current = resolved card icon_size × resolved per-marker size

Новый визуальный base size:

visual = current × 0.90

Коэффициент применяется после разрешения сохранённых настроек. Поэтому default, явно заданный global icon_size и per-marker size уменьшаются одинаково на 10%, а их относительные различия сохраняются.

7.2. Что масштабируется

От нового visual base зависят:

  • icon/value core, shell, glyph и text;
  • Double/value/legacy sections;
  • state/focus/selection rings, border widths и shadows;
  • marker-owned LQI, disabled/new badges и activity geometry;
  • vacuum puck, поскольку он использует уменьшенный package base icon;
  • preview/static projection того же face.

Glow radius, room geometry, sun, decor, label font, plan camera и координаты не масштабируются. Сохранённая точка остаётся центром icon core. Минимальная интерактивная область остаётся не меньше 44×44 CSS px и не уменьшается вместе с painted face.

7.3. Совместимость настроек

Значения в storage и UI не переписываются и не материализуются. Открытие и сохранение старой настройки не добавляет множитель. House Plan применяет визуальную коррекцию одинаково к старому и новому плану. Пользователь по-прежнему может компенсировать размер существующими global/per-marker controls.

8. Геометрия display: value

Основной value marker остаётся Text shell из пакета #179:

  • высота внутреннего core равна visual base size;
  • ширина растёт по полному тексту и padding, без ellipsis;
  • радиус внутреннего core равен половине его высоты, а не половине ширины;
  • внешний shell повторяет ту же stadium/capsule форму с радиусом половины своей высоты;
  • расстояние между core и shell равно package inset на прямых сторонах и на полукруглых торцах с допустимой растровой погрешностью не более 0,5 CSS px на QA-размерах 32, 56 и 96 px до коэффициента 0,9;
  • сохранённый anchor остаётся в центре исходного icon core, а расширение идёт симметрично влево/вправо.

Исправление относится к основному display: value. Double value section уже имеет нормативный фиксированный pill radius 0.39375 × core; её форма не переопределяется, кроме общего уменьшения 10%.

9. Кому показывается feedback

Источник истины — финальный outcome существующего action resolver/path, а не icon, domain или одно наличие tap_action.

Feedback получает activation, который после всех guards:

  • переключает хотя бы одну доступную HA target либо virtual light;
  • выполняет допустимую cover operation;
  • запускает разрешённый script/scene/automation action;
  • отправляет другую уже поддерживаемую безопасную service command.

Feedback отсутствует, если activation:

  • открывает House Plan info, HA more-info, Device editor, link или settings;
  • только открывает confirmation и ещё не подтверждён;
  • является secure/no-target/unavailable/missing/unsupported no-op;
  • отменён pan, pinch, drag, long press, context click, вторым pointer, pointercancel либо потерей capture.

Для partial group достаточно одной реально dispatch-нутой target. При confirmation feedback начинается только после положительного подтверждения и повторной валидации target, одновременно с фактическим dispatch.

10. Визуальный contract нажатия

Один accepted action создаёт один цикл:

scale 1.00 → 0.95 → 1.00; total duration 200 ms
  • движение плавное, с minimum scale около середины цикла и без паузы;
  • масштабируется только painted device body/shell относительно собственного центра; hit target, saved anchor, LQI, badges, activity waves и Glow не сжимаются и не сдвигаются;
  • feedback композируется с общей коррекцией 0,9, per-marker size, angle, Text/Double layout и semantic state, не перезаписывая их transform;
  • fill, glyph, semantic color, state ring, opacity и z-index не используются для имитации успешного HA state;
  • цикл начинается в том же interaction turn, что dispatch, и не ждёт HA state;
  • повторный отдельный action перезапускает один текущий цикл с реально видимого значения, не создавая очередь и не блокируя второй допустимый service call;
  • state update не повторяет и не продлевает цикл.

Pointerdown потенциально actionable marker может сохранять обычный browser pressed/active cue, но канонический цикл выше принадлежит только accepted dispatch. Touch compatibility click и keyboard activation создают не более одного цикла.

11. Keyboard, reduced motion и lifecycle feedback

  • Enter/Space на интерактивном marker идут через тот же _clickDevice() и дают тот же цикл ровно один раз при dispatch.
  • Focus и :focus-visible остаются видимыми во время/после feedback.
  • При prefers-reduced-motion: reduce scale tween отсутствует. Accepted action получает краткий theme-safe outline/brightness accent минимум на один painted frame без смены semantic цвета или unavailable opacity.
  • Быстрый mode/space change, visibility hidden, disconnect/remount и удаление marker отменяют незавершённую animation без остаточного class/style.
  • Feedback не меняет action debounce, confirmation или service payload.

12. Pointer modality и sticky-hover

12.1. Authority

Каждый экземпляр интерактивной карточки имеет локальное состояние:

unknown | mouse | touch | pen
  • начальное unknown не включает pointer-only hover;
  • настоящий PointerEvent(pointerType='mouse') включает mouse;
  • touch и pen немедленно выключают CSS/JS hover и очищают transient state;
  • следующий настоящий mouse/trackpad pointer event возвращает mouse без reload и без произвольного timeout;
  • compatibility MouseEvent после touch не меняет authority;
  • media query не является authority, но CSS hover разрешён только когда фактическая modality — mouse и среда сообщает hover/fine capability;
  • modality не хранится, не синхронизируется между карточками и не живёт в global mutable singleton.

houseplan-space-card применяет тот же pure resolver в своём экземпляре для footer button. Статический план остаётся pointer-inert.

12.2. Cleanup

Один idempotent helper очищает только transient hover:

  • _hoverRoom и hover-owned _tip;
  • DOM gate, разрешающий CSS hover;
  • transient hover ownership вложенных shared components.

Он вызывается на touch/pen pointerdown, terminal pointerup/pointercancel, lostpointercapture, начале/окончании multi-touch/pinch, terminal tap/click, mode/space change, visibilitychange в hidden и disconnect. Cleanup не снимает DOM focus, не закрывает dialog/help popover, не отменяет action, pointer capture другого owner либо semantic/selected/pressed state.

12.3. JS room/device tooltip

  • room hover использует pointer events либо delegated pointer path и записывает _hoverRoom только при разрешённой mouse modality;
  • device/room tooltip не создаётся из touch/pen либо synthetic mouse;
  • mouse leave очищает только state своего текущего target;
  • следующий настоящий mouse move/enter заново hit-test-ит target, а не восстанавливает stale room/device id;
  • будущий #152 обязан использовать canonical room hit resolver, а не _hoverRoom; #212 сам room click-to-fit не реализует.

13. CSS hover inventory

Все пользовательски заметные :hover в full card получают один явный modality gate. Это включает:

  • View rooms, device markers, openings, room labels/links/gears и vacuum;
  • header tabs, zoom/settings buttons и kiosk/shared controls;
  • shared menus/options/candidates/actions, close controls и links;
  • hp-dialog, hp-help trigger и hp-color-opacity trigger, когда они используются внутри full card;
  • footer action houseplan-space-card.

Rules, объединяющие :hover и :focus-visible, разделяются: hover требует mouse gate, keyboard focus — нет. Alarm/working/open/lock/unavailable/selected state не зависят от modality. Unavailable по-прежнему не получает visual hover.

Чисто editor-only handles могут оставаться best effort, но naked selector допустим только если source-contract test документирует, что target никогда не появляется в View/shared component. Предпочтительный безопасный вариант — гейтить весь общий cardStyles единообразно, не меняя editor actions.

Открытый по click/tap hp-help popover остаётся намеренно toggled surface; его жизненный цикл не считается hover. Гейт касается только визуального hover его trigger.

14. UX, accessibility и touch policy

  • View и kiosk на desktop/touch остаются блокирующими поверхностями.
  • Device/Plan/Background editors остаются desktop-first; общие controls получают no-sticky-hover автоматически, но новая touch parity не обещается.
  • Touch target marker не меньше 44×44 CSS px после уменьшения face.
  • Accessible name, role, tabindex, focus order и secure confirmation не меняются.
  • Screen reader announcement о feedback не добавляется: input принят, но HA ещё не подтвердил изменение состояния.
  • Touch → dialog → close не возвращает hover marker из старого кадра.
  • Pan, pinch, long press и pointer cancellation не запускают action/feedback и не оставляют hover.
  • В Flat/hidden Isometric, light/dark и kiosk действует одна политика.

15. Данные, migration и i18n

Новых config/layout/localStorage/backend полей нет. Существующие размеры, координаты, display, value, pulse, LQI и action settings round-trip без записи. Migration не нужна.

Новых пользовательских строк не ожидается. Если реализация потребует строку, это расширение scope: обязательны RU/EN parity и отдельное решение владельца.

16. Архитектурный contract и затронутые файлы

Обязательная цепочка сохраняется:

HA/config state
  → resolveDevicePresentation
  → renderDeviceFace
  → one shared face geometry on full / preview / static surfaces

PointerEvent
  → one instance-local modality resolver
  → JS transient-hover owner + explicit CSS/child-component gate

accepted _clickDevice dispatch
  → one retargetable visual feedback owner

Ожидаемые файлы/модули:

  • src/device-face.ts — общий face DOM только при необходимости отдельного press body;
  • src/styles.ts — коэффициент 0,9, Text pill, press и gated shared hover;
  • src/houseplan-card.ts — modality/cleanup, room tooltip, action feedback и lifecycle;
  • новый малый pure helper src/pointer-modality.ts либо эквивалентный модуль;
  • src/hp-dialog.ts, src/hp-help.ts, src/hp-color-opacity.ts — явный nested hover gate без собственного global detector;
  • src/space-card.ts — локальный gate footer button и shared face parity;
  • src/hp-device-preview.ts/src/space-render.ts — только если parity требует явной передачи, второй renderer запрещён;
  • unit tests, targeted browser smokes, golden matrix и документация из §19.

Конкретное имя helper/class и выбор CSS attribute являются техническими деталями. Нельзя создавать второй action resolver, второй device face renderer или global session latch наподобие текущего _touchSeen.

17. Edge cases

  • marker sizes 32/56/96 px до коэффициента 0,9, per-marker scale 0.5…3;
  • короткое, длинное, кириллическое и CJK value, 0, false, unit symbol;
  • Text, Double right/left/top/bottom, legacy third section и LQI;
  • active/alarm/lock/unlock/selected/focus/virtual/unavailable во время feedback;
  • explicit pulse color/size, reduced motion и continuous pulse;
  • click/tap с медленным HA, rejected Promise после dispatch и state update раньше окончания 200 ms;
  • confirmation accept/cancel и target, изменившийся пока dialog открыт;
  • rapid double action, touch compatibility click и Enter/Space;
  • tap → dialog → close, long press, pan, pinch, second pointer, pointercancel, lost capture;
  • touch-only browser, браузер с ложным (hover: hover), hybrid touch → mouse;
  • mouse pointer впервые входит без предварительного click;
  • mode/space/visibility/remount во время hover либо press;
  • два full card и static card на одной странице: modality одного экземпляра не изменяет другой;
  • Light/Dark, Flat/hidden Isometric, View/kiosk/Device editor/static card.

18. Acceptance criteria

  1. AC1 — 10% geometry. Painted core/shell/glyph/value/sections/rings/badges, marker LQI/activity geometry и vacuum puck имеют линейный размер 0.90 ± 0.005 от pre-#212 reference при одинаковых settings на full, preview и static surfaces. Доказательство: unit/source facts + computed-style browser smoke + reviewed 32/56/96 golden/reference matrix.
  2. AC2 — anchor и hit area. Saved coordinates, Text/Double anchor и relative per-marker scale не меняются; интерактивный target остаётся минимум 44×44 CSS px. Доказательство: unit geometry + full View browser smoke.
  3. AC3 — value capsule. Широкий display: value имеет внутренний и внешний stadium radius по половине соответствующей высоты и равномерный inset с погрешностью ≤0,5 CSS px; полный текст не обрезан. Доказательство: exact style/layout assertions + long-value Light/Dark golden.
  4. AC4 — accepted feedback. Реально dispatch-нутый click/tap/Enter/Space даёт один цикл 1 → .95 → 1 общей длительностью 200 ± 20 ms, не ожидая HA state. Доказательство: fake-clock unit + desktop/touch/keyboard smoke.
  5. AC5 — точный gate действия. Info/more-info/editor/link, secure/no-target/ unavailable no-op, cancel confirmation и отменённый gesture не получают канонический цикл; accepted confirmation получает его при dispatch. Доказательство: resolver/outcome matrix + browser smoke.
  6. AC6 — composition и bounded lifecycle. Feedback не меняет state colors, pulse, Glow, badges, LQI, angle, hit area или service payload; repeat retargets один effect без очереди, lifecycle cleanup не оставляет residue. Доказательство: unit lifecycle/composition + semantic-state smoke.
  7. AC7 — reduced motion и focus. В reduce нет scale tween, accepted action виден минимум один frame через несемантический accent; focus-visible и DOM focus сохраняются. Доказательство: media-query/keyboard smoke + golden.
  8. AC8 — modality authority. unknown/mouse/touch/pen переходы instance-local; touch/pen выключают hover, настоящий mouse возвращает его без reload, compatibility mouse не возвращает. Доказательство: pure unit matrix + real-touch/hybrid browser smoke.
  9. AC9 — JS hover cleanup. После touch terminal event, cancel, lost capture, pinch, mode/space/hidden/disconnect _hoverRoom и hover-owned _tip очищены не позднее следующего painted frame. Доказательство: unit/source contract
    • browser state assertions.
  10. AC10 — CSS/nested hover. В View/shared surfaces нет naked visual :hover; device/room/opening/vacuum/header/dialog/help/color/static-button styles требуют mouse gate, а focus/semantic state не требуют его. Доказательство: CSS inventory test + touch computed-style smoke.
  11. AC11 — desktop/hybrid parity. Desktop mouse hover впервые включается на pointer entry и выглядит как до #212; hybrid touch → mouse восстанавливает текущий hit, не stale state. Доказательство: mouse/hybrid smoke + reviewed hover golden.
  12. AC12 — gesture и action safety. Pan/pinch/long press/second pointer/ pointercancel не вызывают ложный click, feedback или hover; secure lock и confirmation invariants не меняются. Доказательство: existing gesture and secure-action smokes + targeted regression.
  13. AC13 — surface parity. Full View, kiosk, Device preview и static card используют один face contract; static plan остаётся non-interactive, Device editor остаётся desktop-first. Доказательство: renderer unit + named preview/static/kiosk smokes.
  14. AC14 — no data/i18n change. Open → Save и serialization не меняют size/display/action data; backend и RU/EN key set неизменны. Доказательство: serialization/i18n unit + code review.
  15. AC15 — documentation address. Hover/pressed/semantic ownership обновлён в docs/UX-MODES.md; docs/CANVAS.md не получает несвойственный раздел. Доказательство: docs diff + check-docs.
  16. AC16 — performance. 200 markers не получают per-frame JS, per-marker media listener, layout loop либо рост постоянных animation layers; pointer move не вызывает full Lit render на каждый пиксель. Доказательство: source review + pre-beta performance profile.

19. План тестирования и release-артефакты

19.1. Цикл реализации до S7

Обязательны:

npm run typecheck
npm test
npm run build
node scripts/check-docs.mjs --external

Targeted browser smokes:

  • расширенный demo/smoke_device_icon_design.mjs — 0,9 и value capsule;
  • demo/smoke_device_preview_parity.mjs;
  • demo/smoke_static_icon.mjs;
  • demo/smoke_state_value.mjs;
  • demo/smoke_icon_scale.mjs;
  • новый/расширенный device action feedback smoke;
  • расширенный demo/smoke_touch_tips.mjs либо отдельный real-touch hover reset;
  • demo/smoke_long_press_gesture.mjs;
  • secure confirmation/lock and opening/vacuum hover regressions.

Перед S7 нужны failing-before-fix доказательства как минимум для коэффициента размера, value radius, accepted feedback и touch sticky-hover. Для критичных guards добавляются mutation checks либо эквивалентное документированное mutation proof.

19.2. Golden и visual QA

Проверить Light/Dark:

  • state-table 32/56/96 с новым размером;
  • длинный основной Value рядом с reference capsule;
  • normal press midpoint и reduced-motion accent;
  • desktop hover, post-touch no-hover и focus-visible;
  • semantic active/alarm/selected во время feedback.

Локальный Windows capture диагностический. Baseline принимается только из reviewed полного Linux CI artefact перед beta по release runbook.

19.3. Перед beta

Выполняются полный browser smoke, Linux golden и performance gates из HOUSEPLAN-CODEX-SESSION-RUNBOOK.md. Полный HA harness каноничен в Linux CI из-за fcntl.

19.4. Документация и changelog

User-visible implementation commit с User-Visible: yes одновременно обновляет:

  • docs/CHANGELOG.md и docs/CHANGELOG.ru.md со ссылкой на #212;
  • docs/USER-GUIDE.ru.md — меньший marker face, accepted-action feedback и отсутствие sticky hover;
  • docs/TOUCH-SUPPORT.md — event-derived modality и hybrid contract;
  • docs/UX-MODES.md — hover/pressed/semantic ownership, закрывая #181;
  • docs/TESTING.md — named size/value/feedback/real-touch/hybrid evidence;
  • документационные screenshots, если их source fingerprint/вид изменился.

docs/CANVAS.md не обновляется ради hover ownership. #22/#154/#181 не закрываются и не получают S8-merged автоматически: владелец обработает их после merge #212.

20. Риски и откат

Риск Мера
Пользовательские tuned sizes уменьшаются дважды ровно один общий factor после resolver; computed parity tests
Press обещает успех вместо принятого input неизменный semantic state; start только при dispatch
Scale ломает translate/angle/Text shell независимый visual layer/individual transform + composition test
Touch compatibility event возвращает hover PointerEvent authority + CSS gate, без timeout
Gate убирает keyboard focus hover/focus selectors разделены
Cleanup снимает selection/action helper владеет только _tip/_hoverRoom/gate
Две карточки влияют друг на друга instance-local controller, без static singleton
Pointer move вызывает render storm imperative host attribute/state transition only on modality change
Общий CSS пропускает nested shadow component явный child property/attribute + source inventory

Откат одним implementation revert возвращает прежний visual factor, value radius, feedback и hover path. Данных, backend migration и rollback storage нет. Возврат к sticky touch hover либо неверной value geometry не является допустимым визуальным fallback.

21. План реализации

  1. Добавить failing tests/fixtures для 0,9, value capsule, feedback и modality.
  2. Вынести instance-local pointer modality/cleanup contract и подключить full card, nested shared components и static footer.
  3. Перевести room tooltip/hover на gated pointer path и закрыть CSS inventory.
  4. Применить один visual factor к shared face, сохранив 44×44 hit/anchor.
  5. Исправить радиус основного Value core.
  6. Подключить один retargetable 200 ms feedback в фактические dispatch points.
  7. Обновить docs/changelogs/screenshots и выполнить цикл §19.1.
  8. Передать один полный диапазон #212 в S7; linked issue не закрывать.

22. Принятые технические предположения

Следующее принято предположительно и может быть свободно изменено ревьюером без нового продуктового решения, если сохраняются AC:

  1. Factor 0,9 реализуется одной CSS custom property в общем face, а не переписыванием config defaults.
  2. Value capsule исправляется постоянным радиусом visual core / 2.
  3. Pointer modality живёт в малом pure resolver; DOM hover gate меняется императивно только при смене состояния, без requestUpdate на каждый move.
  4. Nested shadow components получают boolean/attribute от owning full card и не создают собственный global listener.
  5. Press feedback может использовать Web Animations API либо отдельную inner shell property, если поддерживает restart/cancel и не меняет hit geometry.
  6. Smooth 200 ms curve может использовать package easing cubic-bezier(.22,.61,.36,1); exact easing не является config surface.
  7. Reduced-motion accent использует существующий theme/focus token и один painted-frame owner, не новую пользовательскую строку.
  8. Формулировка #22 plan-wide setting означает одну общую политику feedback для всех actionable markers плана, а не новую пользовательскую настройку либо per-marker override.