🔴이 릴리스는 모션 축을 신설하면서 CHANGELOG 에 "이 축을 경유하는 모든 애니메이션이
함께 멈춘다"고 적었는데, 실측하니 경유하는 것이 0개였다. 시트에 토큰이 있고
prefers-reduced-motion 블록도 있었지만 어떤 컴포넌트도 그 축을 읽지 않았다.
접근성 약속이 문서에만 있었다.
■ 배선
transition 37곳 / 24파일. 컴포넌트-로컬 --switch-duration 의 기본값도 공용 축에서
파생시켰다 — 그러지 않으면 그 컴포넌트만 비껴간다.
⚠지속시간이 계단으로 접히면서 값이 움직인다(최대 편차 진행바 0.4s → 0.32s, -20%).
나머지는 ±10% 이내다. 값 보존 대신 계단을 고른 이유: 7가지 지속시간을 그대로
토큰화하면 축이 아니라 사전이 되고, 그러면 전수 경유가 성립하지 않는다.
■ 회귀 테스트 2종
컴포넌트 시트에 리터럴 지속시간 0건(폴백은 제외 — 시트 부재 시 렌더를 살린다) ·
로컬 지속시간 토큰도 공용 축에서 파생. 네거티브 컨트롤 확인: 한 곳을 리터럴로
되돌리면 그 줄을 정확히 지목하고, 복원하면 초록이 된다.
★기존 두 단언(토큰 존재·reduced-motion 블록)은 둘 다 통과하고 있었다 — 시트만
보기 때문이다. 축의 계약은 "토큰이 있다"가 아니라 "컴포넌트가 그것을 지난다"이다.
■ 폴백 대조기 결함 — 조건부 at-rule 안의 값을 정본으로 읽었다
prefers-reduced-motion 블록이 --u-duration-* 를 0ms 로 재선언하는데 파서가 뒤에 온
값을 남겨, 배선된 폴백 55건이 전부 "시트와 불일치"로 보고됐다. 폴백의 계약은
"시트가 없을 때 이 리터럴로 렌더한다"이고 시트가 없는 환경에는 미디어 조건도 없다
— 무조건 선언이 유일하게 정합한 값이다. @media·@supports·@container 블록을 걷어낸다.
■ 타이포 축
이 축의 1차 소비자는 컴포넌트가 아니라 소비 앱이다(화면의 제목·라벨·캡션).
값이 이미 단과 일치하는 자리에만 배선했다 — 시각 변경 0.
남은 것: u-dialog·u-drawer 제목이 18px 인데 스케일에 18px 단이 없다. 사람 판단.
검증: tsc 0 · eslint 0 · 242/242 · tokens:sync 일치 · sweep 0건