Перевірка

Піксельний доказ

Дев'яносто три кроки етапу 08 переписали продукт зсередини. Ця сторінка ставить одне питання і відповідає на нього браузером, а не переказом: що з цього видно на екрані - і чи зрушило щось, чого ніхто не вирішував.

база: 9e4410940 екранів390 і 1280160 завантажень165 рішень у таблиці
Як це заміряно

Два дерева, один браузер, одна мить. «До» це git archive 9e44109 - останній коміт перед першим кроком етапу 08, - розгорнутий у власну теку й відданий власним сервером. «Після» це робоче дерево. Обидва відкриває той самий headless Chrome, з тими самими ширинами, тим самим шрифтом і тим самим вимкненим prefers-reduced-motion. Різниця, яку дає прилад, дорівнює нулю за побудовою: прилад один.

І з 13.08.2026 це робить прилад, а не руки: tools/proof.mjs. Сорок екранів, обидві половини, один Chrome, один прогін. Раніше набір знімався один раз, вручну, 06.08 - і коли світла тема зрушила через тиждень, перезняти його було нічим: умови зйомки ніде не записані. Перша спроба перезняти тільки «після» повідомила, що зрушили всі 40 екранів на 2-15%, з різницею каналу до 255, і карта різниць сказала чому: кожен гліф на кожному екрані був обведений двічі. Це субпіксельний рендер тексту, а не розкладка. Тому «до» перезнімається теж - із того самого git archive 9e44109, у ту саму мить, тим самим браузером. Порівняння - по пікселях, а не по байтах: JPEG кодує Chrome, тож інший Chrome пише інші байти для тієї самої картинки, і байтова перевірка відповідає «змінилось» на все, тобто не вміє відповісти «ні».

Прилад називає елемент, а не тільки процент. Змінені пікселі групуються в області по сітці 8px, і центр кожної області питає сторінку elementFromPoint. Без цього правило «кожна різниця пояснюється рядком іменованого списку» перевірити неможливо: процент каже, що екран зрушив, і мовчить про те, що саме на ньому зрушило.

Один екран із сорока не зрушив зовсім - 0.000%. Це overview, і він єдиний, бо він єдиний не на системі: хаб етапу побудований на роадмеп-хромі /_nav.css, як і кореневий index.html. Нуль тут не заслуга, це контроль з іншого боку - прилад, який показав би різницю й там, показував би шум.

Позитивний контроль узято першим. Перед будь-яким заміром два сервери порівняли між собою: design/cart.html віддає 52 різні рядки, і серед них видно суть етапу - базове дерево вантажить wireframes/_wf.css та design/kit/kit.css, робоче вантажить design/system/index.css. Прилад, який не бачить різниці там, де вона є, не може засвідчити її відсутність деінде.

Чому не поелементний diff

За дев'яносто три кроки змінилась і сама розмітка: атоми отримали класи, обгортки з'явились і зникли, знаки стали SVG. Поелементне порівняння звітувало б про перебудову, а не про її наслідок, і потонуло б у шумі власного методу.

Тому питають інше: те, що етап проголосив. Одна редакція кожного значення, шкала зі щаблями, ціль, до якої дістає палець, знак, який намальовано, а не набрано. Кожне з цих тверджень - число, яке браузер уміє повернути, і воно повертається з обох дерев однаково.

Десять тверджень, заміряних на обох деревах
Кеглів у продукті, різних
43→28
Об'єднання по всіх 40 екранах на 390. Шкала має 10 щаблів; решта того, що лишилось, - розміри похідні, а не оголошені: знак валюти це .55em ціни поруч (заміряно 16.5 і 19.8), кінцева позначка - 1.15em свого підпису.
Кеглів на одному екрані, у середньому
16.1→8.2
Не «менше тексту», а вдвічі менше рішень про розмір на одному екрані.
Радіусів, різних
15→9
Було 4 · 5 · 6 · 7 · 8 · 9 · 10 · 11 · 12 · 14 · 16 · 18 · 20 · 50 · 100. Стало 4 · 5 · 6 · 8 · 12 · 16 · 20 · 50 · 100. З того, що лишилось, 5 і 6 живуть на overview, product-coach - і жодне з них не щабель.
Товщин лінії
3→3
Обидва дерева дають 1 · 2 · 4px, і саме ця незмінність і є знахідкою: 1.5px не намальовано в жодному з них, бо Chrome зводить його до 1 ще до розкладки. Крок 7.62 прибрав 33 оголошення значення, якого продукт ніколи не малював.
Екранів із накресленням 800
32→1
Inter вантажиться як 400/500/600/700 - грані 800 немає, і Chrome її не синтезує, тож 800 малювалось як 700. Крок 7.65 назвав це вголос. Лишився один екран: account-error.
Екранів з Arial у розмітці
31→2
Не «шрифт змінився» - гарнітура на екрані та сама. Змінилось те, куди браузер падає, якщо Inter немає: літерал казав «Inter, і далі нічого». Лишилось два: listing-sheet, overview.
Знаків, намальованих шрифтом
1552→284
Символи з емодзі-діапазонів у тексті всіх 40 екранів. Знак, набраний символом, змінюється разом зі шрифтом, не тримає товщину штриха і озвучується вголос.
Знаків, намальованих набором
3668→5343
Inline-SVG на тих самих екранах: один малюнок, один штрих 1.9, aria-hidden.
Імен у :root
21→199
Значення з іменем - це рішення, під яким хтось підписався; літерал - те саме рішення без підпису.
Екранів, що їдуть убік
0→0
На 390 і 1280 їх не було й до етапу: усі переповнення, які цей етап полагодив, жили в смугах 480-620 і на 720, а цих двох ширин вони не торкались. Нуль тут - це не заслуга, це контроль.

Чотири речі, які цей замір знайшов сам

Жодна з них не була завданням кроку - їх видно тільки тоді, коли ті самі числа знімають з двох дерев поспіль.
  • Накреслення 900 стоїть на 17 екранах, і до етапу стояло рівно на тих самих 17. Заміряно на index.html: це вісім <b> без класу. У шкалі 900 немає, Inter його не вантажить, і жоден крок його не називав. Чий це рядок - [?]
  • Радіуси 5 і 6 лишились на overview, product-coach - обидва поза шкалою 4/8/12/16
  • Arial дожив на двох сторінках із 31: listing-sheet, overview
  • Жоден екран не має нуля набраних знаків, і причина не в продукті: ← і ↗ у службовій смузі стенда стоять на кожній сторінці. Із самого продукту лишились мінус усередині числа («−15%» у чипі знижки), ≈ у «≈ 18 ₴ / порція» - обидва арифметика, а не позначка контрола, - і 🗳 📦 💴 в адресах, де два гліфи, 🔳 і 🚚, не мають запису в наборі взагалі (знахідка 7.87)

І одне число, яке доказом НЕ є

Контролів, чия менша сторона менша за 44px: 3089 до і 2767 після на 390. Майже не зрушило - і це чесно: замір рахує кожне посилання всередині речення, а посилання в тексті ціллю на 44px бути не мусить. Крок 7.33 давав пальцю не розмір, а відповідь: 3 351 контрол отримав стан :active, якого не мав. Число вище цього не бачить, тож воно тут як інвентар, а не як оцінка.
До і після на всіх 40 екранах

Перший екран телефона, 390×844, той самий кадр з обох дерев. Тягніть ручку - або візьміть її з клавіатури стрілками. Два зображення поруч просять око тримати дві картинки в голові й порівнювати їх по пам'яті; витирання кладе різницю на одні координати, і тоді зсув на 4px це зсув на 4px, а не відчуття.

Кабінет покупця - Огляд - Stack (wireframe 7.0) - до етапу 08Кабінет покупця - Огляд - Stack (wireframe 7.0) - після етапу 08допісля
Кабінет покупця - Огляд - Stack (wireframe 7.0)
кеглів 19 → 11 · знаків шрифтом 48 → 9 · радіусів 9 → 5
Кабінет - Адреси - Stack (wireframe 7.5) - до етапу 08Кабінет - Адреси - Stack (wireframe 7.5) - після етапу 08допісля
Кабінет - Адреси - Stack (wireframe 7.5)
кеглів 15 → 7 · знаків шрифтом 51 → 21 · радіусів 8 → 5
Кабінет покупця - новий акаунт - Stack (wireframe 7.0 · порожньо) - до етапу 08Кабінет покупця - новий акаунт - Stack (wireframe 7.0 · порожньо) - після етапу 08допісля
Кабінет покупця - новий акаунт - Stack (wireframe 7.0 · порожньо)
кеглів 18 → 9 · знаків шрифтом 42 → 9 · радіусів 9 → 5
Кабінет покупця - помилка - Stack (wireframe 7.0 · помилка) - до етапу 08Кабінет покупця - помилка - Stack (wireframe 7.0 · помилка) - після етапу 08допісля
Кабінет покупця - помилка - Stack (wireframe 7.0 · помилка)
кеглів 12 → 6 · знаків шрифтом 33 → 4 · радіусів 8 → 5
Кабінет покупця - завантаження - Stack (wireframe 7.0 · завантаження) - до етапу 08Кабінет покупця - завантаження - Stack (wireframe 7.0 · завантаження) - після етапу 08допісля
Кабінет покупця - завантаження - Stack (wireframe 7.0 · завантаження)
кеглів 9 → 5 · знаків шрифтом 33 → 4 · радіусів 9 → 5
Кабінет - Знижки та бонуси - Stack (wireframe 7.4) - до етапу 08Кабінет - Знижки та бонуси - Stack (wireframe 7.4) - після етапу 08допісля
Кабінет - Знижки та бонуси - Stack (wireframe 7.4)
кеглів 17 → 9 · знаків шрифтом 43 → 12 · радіусів 8 → 5
Кабінет - Замовлення - Stack (wireframe 7.2) - до етапу 08Кабінет - Замовлення - Stack (wireframe 7.2) - після етапу 08допісля
Кабінет - Замовлення - Stack (wireframe 7.2)
кеглів 19 → 8 · знаків шрифтом 44 → 15 · радіусів 10 → 5
Кабінет - Профіль - Stack (wireframe 7.1) - до етапу 08Кабінет - Профіль - Stack (wireframe 7.1) - після етапу 08допісля
Кабінет - Профіль - Stack (wireframe 7.1)
кеглів 16 → 7 · знаків шрифтом 43 → 11 · радіусів 8 → 5
Кабінет - Обране - Stack (wireframe 7.6) - до етапу 08Кабінет - Обране - Stack (wireframe 7.6) - після етапу 08допісля
Кабінет - Обране - Stack (wireframe 7.6)
кеглів 15 → 8 · знаків шрифтом 43 → 8 · радіусів 8 → 5
Вхід або реєстрація - Stack (wireframe 1.x) - до етапу 08Вхід або реєстрація - Stack (wireframe 1.x) - після етапу 08допісля
Вхід або реєстрація - Stack (wireframe 1.x)
кеглів 13 → 7 · знаків шрифтом 34 → 4 · радіусів 7 → 4
Введіть код зі SMS - Stack (wireframe 1.1) - до етапу 08Введіть код зі SMS - Stack (wireframe 1.1) - після етапу 08допісля
Введіть код зі SMS - Stack (wireframe 1.1)
кеглів 11 → 7 · знаків шрифтом 35 → 5 · радіусів 7 → 4
Невірний код - Stack (wireframe 1.1 error) - до етапу 08Невірний код - Stack (wireframe 1.1 error) - після етапу 08допісля
Невірний код - Stack (wireframe 1.1 error)
кеглів 12 → 7 · знаків шрифтом 35 → 5 · радіусів 7 → 4
Надсилаємо код - Stack (wireframe 1.x loading) - до етапу 08Надсилаємо код - Stack (wireframe 1.x loading) - після етапу 08допісля
Надсилаємо код - Stack (wireframe 1.x loading)
кеглів 12 → 6 · знаків шрифтом 36 → 5 · радіусів 9 → 5
Як вас звати? - Stack (wireframe 1.2) - до етапу 08Як вас звати? - Stack (wireframe 1.2) - після етапу 08допісля
Як вас звати? - Stack (wireframe 1.2)
кеглів 12 → 7 · знаків шрифтом 35 → 5 · радіусів 8 → 4
Кошик - Stack (wireframe 6.0) - до етапу 08Кошик - Stack (wireframe 6.0) - після етапу 08допісля
Кошик - Stack (wireframe 6.0)
кеглів 15 → 7 · знаків шрифтом 38 → 5 · радіусів 9 → 4
Кошик порожній - Stack (wireframe 6.0 · empty) - до етапу 08Кошик порожній - Stack (wireframe 6.0 · empty) - після етапу 08допісля
Кошик порожній - Stack (wireframe 6.0 · empty)
кеглів 12 → 6 · знаків шрифтом 34 → 4 · радіусів 8 → 4
Кошик - товар недоступний - Stack (wireframe 6.0 · oos) - до етапу 08Кошик - товар недоступний - Stack (wireframe 6.0 · oos) - після етапу 08допісля
Кошик - товар недоступний - Stack (wireframe 6.0 · oos)
кеглів 16 → 7 · знаків шрифтом 38 → 5 · радіусів 9 → 4
Оформлення замовлення - Stack (wireframe 6.1) - до етапу 08Оформлення замовлення - Stack (wireframe 6.1) - після етапу 08допісля
Оформлення замовлення - Stack (wireframe 6.1)
кеглів 20 → 8 · знаків шрифтом 11 → 4 · радіусів 10 → 5
Оплату не завершено - Stack (wireframe 6.1 · declined) - до етапу 08Оплату не завершено - Stack (wireframe 6.1 · declined) - після етапу 08допісля
Оплату не завершено - Stack (wireframe 6.1 · declined)
кеглів 13 → 7 · знаків шрифтом 4 → 4 · радіусів 7 → 5
Обробляємо оплату… - Stack (wireframe 6.1 · loading) - до етапу 08Обробляємо оплату… - Stack (wireframe 6.1 · loading) - після етапу 08допісля
Обробляємо оплату… - Stack (wireframe 6.1 · loading)
кеглів 10 → 5 · знаків шрифтом 4 → 3 · радіусів 7 → 5
Оформлення замовлення (у кабінеті) - Stack (wireframe 6.1 · logged-in) - до етапу 08Оформлення замовлення (у кабінеті) - Stack (wireframe 6.1 · logged-in) - після етапу 08допісля
Оформлення замовлення (у кабінеті) - Stack (wireframe 6.1 · logged-in)
кеглів 19 → 8 · знаків шрифтом 14 → 6 · радіусів 10 → 5
Оформлення - вкажіть адресу - Stack (wireframe 6.1 · no-address) - до етапу 08Оформлення - вкажіть адресу - Stack (wireframe 6.1 · no-address) - після етапу 08допісля
Оформлення - вкажіть адресу - Stack (wireframe 6.1 · no-address)
кеглів 19 → 8 · знаків шрифтом 14 → 6 · радіусів 10 → 5
Stack - спортивне харчування (wireframe 0.0, головна) - до етапу 08Stack - спортивне харчування (wireframe 0.0, головна) - після етапу 08допісля
Stack - спортивне харчування (wireframe 0.0, головна)
кеглів 23 → 11 · знаків шрифтом 67 → 9 · радіусів 13 → 6
Stack - спортивне харчування (wireframe 0.0, головна) - до етапу 08Stack - спортивне харчування (wireframe 0.0, головна) - після етапу 08допісля
Stack - спортивне харчування (wireframe 0.0, головна)
кеглів 24 → 11 · знаків шрифтом 68 → 9 · радіусів 13 → 6
Stack - спортивне харчування (wireframe 0.0, головна) - до етапу 08Stack - спортивне харчування (wireframe 0.0, головна) - після етапу 08допісля
Stack - спортивне харчування (wireframe 0.0, головна)
кеглів 23 → 11 · знаків шрифтом 67 → 10 · радіусів 13 → 6
Stack - спортивне харчування (wireframe 0.0, головна) - до етапу 08Stack - спортивне харчування (wireframe 0.0, головна) - після етапу 08допісля
Stack - спортивне харчування (wireframe 0.0, головна)
кеглів 23 → 11 · знаків шрифтом 70 → 12 · радіусів 13 → 6
Категорія «Протеїн» - Stack (wireframe 2.1, еталон) - до етапу 08Категорія «Протеїн» - Stack (wireframe 2.1, еталон) - після етапу 08допісля
Категорія «Протеїн» - Stack (wireframe 2.1, еталон)
кеглів 16 → 8 · знаків шрифтом 48 → 7 · радіусів 12 → 4
Категорія «Протеїн» - порожня видача (wireframe 2.1) - до етапу 08Категорія «Протеїн» - порожня видача (wireframe 2.1) - після етапу 08допісля
Категорія «Протеїн» - порожня видача (wireframe 2.1)
кеглів 14 → 7 · знаків шрифтом 37 → 4 · радіусів 10 → 5
Категорія «Протеїн» - помилка завантаження (wireframe 2.1) - до етапу 08Категорія «Протеїн» - помилка завантаження (wireframe 2.1) - після етапу 08допісля
Категорія «Протеїн» - помилка завантаження (wireframe 2.1)
кеглів 15 → 8 · знаків шрифтом 34 → 4 · радіусів 10 → 4
Категорія «Протеїн» - з фільтрами (wireframe 2.1) - до етапу 08Категорія «Протеїн» - з фільтрами (wireframe 2.1) - після етапу 08допісля
Категорія «Протеїн» - з фільтрами (wireframe 2.1)
кеглів 16 → 8 · знаків шрифтом 44 → 5 · радіусів 12 → 4
Категорія «Протеїн» - списком (wireframe 2.1) - до етапу 08Категорія «Протеїн» - списком (wireframe 2.1) - після етапу 08допісля
Категорія «Протеїн» - списком (wireframe 2.1)
кеглів 17 → 9 · знаків шрифтом 44 → 6 · радіусів 11 → 4
Категорія «Протеїн» - завантаження (wireframe 2.1) - до етапу 08Категорія «Протеїн» - завантаження (wireframe 2.1) - після етапу 08допісля
Категорія «Протеїн» - завантаження (wireframe 2.1)
кеглів 13 → 7 · знаків шрифтом 34 → 4 · радіусів 9 → 3
Категорія «Протеїн» - фільтри (wireframe 2.1 · sheet) - до етапу 08Категорія «Протеїн» - фільтри (wireframe 2.1 · sheet) - після етапу 08допісля
Категорія «Протеїн» - фільтри (wireframe 2.1 · sheet)
кеглів 16 → 8 · знаків шрифтом 48 → 7 · радіусів 12 → 5
Stack - UI Visual - до етапу 08Stack - UI Visual - після етапу 08допісля
Stack - UI Visual
кеглів 18 → 18 · знаків шрифтом 6 → 6 · радіусів 6 → 6
Gold Standard 100% Whey 2270 г - Stack (wireframe 3.0) - до етапу 08Gold Standard 100% Whey 2270 г - Stack (wireframe 3.0) - після етапу 08допісля
Gold Standard 100% Whey 2270 г - Stack (wireframe 3.0)
кеглів 22 → 10 · знаків шрифтом 59 → 11 · радіусів 14 → 6
Gold Standard 100% Whey 2270 г - Кабінет тренера (wireframe 3.0 · coach) - до етапу 08Gold Standard 100% Whey 2270 г - Кабінет тренера (wireframe 3.0 · coach) - після етапу 08допісля
Gold Standard 100% Whey 2270 г - Кабінет тренера (wireframe 3.0 · coach)
кеглів 23 → 11 · знаків шрифтом 59 → 11 · радіусів 15 → 7
Картка товару - помилка (wireframe 3.0) - до етапу 08Картка товару - помилка (wireframe 3.0) - після етапу 08допісля
Картка товару - помилка (wireframe 3.0)
кеглів 11 → 7 · знаків шрифтом 33 → 4 · радіусів 7 → 4
Картка товару - завантаження (wireframe 3.0) - до етапу 08Картка товару - завантаження (wireframe 3.0) - після етапу 08допісля
Картка товару - завантаження (wireframe 3.0)
кеглів 9 → 5 · знаків шрифтом 33 → 4 · радіусів 7 → 4
Gold Standard 100% Whey - немає в наявності (wireframe 3.0) - до етапу 08Gold Standard 100% Whey - немає в наявності (wireframe 3.0) - після етапу 08допісля
Gold Standard 100% Whey - немає в наявності (wireframe 3.0)
кеглів 16 → 9 · знаків шрифтом 42 → 7 · радіусів 12 → 5
Gold Standard 100% Whey - відгуки та сертифікат (wireframe 3.0) - до етапу 08Gold Standard 100% Whey - відгуки та сертифікат (wireframe 3.0) - після етапу 08допісля
Gold Standard 100% Whey - відгуки та сертифікат (wireframe 3.0)
кеглів 19 → 9 · знаків шрифтом 47 → 10 · радіусів 11 → 5
Показано перший екран, не сторінку цілком: саме його бачить людина, і саме на ньому видно шкалу, знаки й повітря. Повна висота сторінки заміряна окремо і входить у таблицю нижче там, де крок її називає.
Що саме зрушило і хто це вирішив

Кожен рядок - крок, змінна, старе значення, нове значення й причина, прочитані з журналу етапу (design/kit/docs/consolidation.md, 9 700 рядків) і ні з чого більше. Де журнал числа не називає, стоїть [?] - не здогад.

165 рухів, з них 136 видно на екрані. Це і є відповідь на питання сторінки: продукт змінився не тому, що хтось перемалював його наново, а тому, що 136 разів було названо змінну, значення й причину.

КрокЩо і яка зміннаБуло → сталоЧому
5.5Radius: thirteen steps to four (212 declarations rewritten, 9 878 radius declarations changed)
border-radius / radius tokens
13 radius tokens + 4 literals4 / 8 / 12 / 16 (+ pill, circle); ties down 10->8, 14->12, 6->4a list, not a system; ties go down because less rounding reads as a tool, more rounding reads as a toy (principle 4)
5.5Icon stroke unified on three glyphs in design/_nav.js (457 stroke-width declarations changed)
stroke-width
1.5 and 1.71.91 931 glyphs were already at 1.9; one stroke at every size, below 14px the stroke compensates
5.5Every text-entry field goes to 16px on mobile (176 font-size + 86 height declarations changed; 67 of 67 visible fields now >=16 at 360)
font-size at max-width: 859px
136 of 166 inputs below 16px--fs-16iOS Safari zooms the whole page when a focused field is under 16px
5.5Four drifted card borders moved to the nearest declared role (27 border-colour declarations changed)
border-color
--grey-dd x3, --grey-f0 x1--line-hair / --line-strongtwo declared roles must carry every hairline; the census over-stated the drift by counting width as colour
5.5The outlined action button takes the control edge (7 rules: .auth-x, .cd-x, .sbtn, .co-soc, .cd-cont, .cd-empty .btn, .co-err-acts .btn)
border-color
--line-hair--line-strongthe line of a button is the edge of a control, and an edge is not a divider; verified 0 outlined buttons still on the hairline
5.5Eleven duplicate colour primitives merged, 22 references repointed (primitives 49 -> 37)
colour primitives (--red-100, --amber-25/75/100, --amber-300, --warm-150, --grey-f1/f2/f3/ee, --grey-cf)
eleven near-duplicate values, pairs inside dL 0-2--red-50, --amber-50, --amber-200, --warm-200, --grey-ec, --grey-ccthe primitive a semantic role reads survives; where neither has a role, the more-read survives
5.5The price filter's number input (.frow .in.uiv-num, 14 instances) finally gets a size
font-size
13.3333px (the browser default)--fs-13the smallest size the system already declares for a field; going below would invent a step
5.5Spacing put on an 8px grid: 937 declarations moved, 19 steps deleted; 16 921 of 47 244 elements touched (36%), 47 270 declarations changed
padding / gap / margin / height / width
27 steps standing 1px apart from 1 to 182 · 4 · 8 · 12 · 16 · 24 · 32 · 40; ties UP (6->8, 10->12, 14->16, 20->24)a ladder with 1px rungs forbids nothing; for spacing more room reads as calmer
5.5The six half-pixel type steps snapped to whole numbers (210 declarations, 26 -> 20 steps; 16 396 elements, 32 833 declarations)
font-size
9.5 · 10.5 · 11.5 · 12.5 · 13.5 · 14.510 · 11 · 12 · 13 · 13 · 14a half pixel was typed by a hand, not asked for by a design, and on a non-retina screen it renders as blur
5.6Font size scale 26 -> 9 rungs (39 995 of 47 244 elements touched, 85%; font-size 33 058 declarations)
font-size
20 steps, 12 neighbour pairs under a ratio of 1.0810 · 12 · 14 · 16 · 18 · 20 · 24 · 30 · 34; ties up (13->14, 11->12, 15->16, 17->18, 19->20, 22->24)every neighbour must hold a ratio of at least 1.10; for text bigger is easier to read
5.6Leading closed to three tokens (line-height 31 635 declarations recomputed)
line-height / base rhythm
6 tokens + 15 literals; body at 1.551 · 1.3 · 1.6; body at 1.6leadings 0.05 apart are not two decisions; the base move is made deliberately and out loud this time
5.6Letter-spacing enters the system (1 831 declarations changed)
letter-spacing
117 literal letter-spacings in 16 values, no token at all--ls-display -.02em · --ls-lead -.01em · --ls-caps .04em · --ls-eyebrow .08emtracking is never a free number: it compensates for size and for case, and there are only four cases here
5.6Three glyphs redrawn - flame, drop, flask (584 svg elements changed: flame 296, flask 144, drop 144, zero others)
glyph ink box / scale
flame 9.9 x 13.9 of ink, centre 3 modules high; drop 11.9 x 15.9, dy -1.00; flask neck 3 modulesflame 13.3 x 18.9, dy 0.00 (scaled 1.42 about the optical centre); drop scaled with it; flask neck 3.6, level line wall to wallagainst a set median of 18.5 the flame read as a small mark floating over its own line; the flask's counters were closing up
5.9The role layer gets the jobs it was missing: 20 primitives and 34 roles added, 154 sites in 45 files rewritten; 547 elements moved on 34 screens and only colour moved
flat colour roles (--scrim-overlay, --mark-faint, --bg-skeleton, --text-price-was, --veil-*, soft status plates)
seven scrim values (.25 .36 .44 .46 .50 .52 .52), #BBBBBB in 21 places, #ECECEC in 13, #AAAAAA in 10, 9 rgba literals--scrim-overlay .52 and the named roles abovea component that has no role to read reads a value, and a component that reads a value cannot be re-themed
6.0Depth becomes a ladder: 307 elements moved on 34 screens and every one moved only box-shadow
box-shadow
97 declarations, 47 distinct values (one flyout at 12/30, 14/34, 16/36, 18/44 in four files)12 levels + 3 rings; 27 distinct valuesa shadow answers exactly one question - how far off the surface is this thing - so the answer has to be a scale; a ring is not an elevation
6.0 (atoms)The Apple and Google marks are sized by INK, not by box (measured on auth, checkout and the showcase)
--brand-ink / brand mark box
apple 13.0 of ink at 18px against google 15.8 at 19pxboth marks 16.0px of ink, in boxes of 19.2 and 22.2equal box is not equal size - a mark with more air in its viewBox has to be given a bigger box to carry the same ink; the buttons did not change height
6.0 (atoms)The phone field's grouping rule moves out of one screen's id into design/system/fields.js (four phone fields, exactly one of them grouped before)
rendered value of a phone field
«4544534353» on the showcase, «32 423 42 34» on the auth screen«67 123 45 67» after a .cc cell, «+380 67 123 45 67» when the field holds the whole numbera rule attached to one id is not a component rule, it is that screen's private habit
6.1The header's chevron on «Каталог» is removed
display
a rotating chevron beside the labeldisplay: none (rest #FF5A00, open #E85200)the button already goes to the pressed fill while the mega menu is open, so the mark repeated a state the fill was already carrying
6.1Квіз, Бонуси, Кошик, Увійти, Обране folded into one finish (four forms, 191 instances; header.css lost eight visual declarations)
button finish
three finishes for five neighbours - Увійти had a ground, Квіз bare text, the two counters outlinesghost: nothing at rest, warm ground + accent ink under the cursorthe row has to say one thing at a time; Каталог stays the only loud thing
6.2The footer's «Підписатись» joins the accent finish at size S (58 instances; the welded field followed the radius)
height / border-radius / border-width / font-size
37 tall, radius 4, 1px border, 12px type, no state at all41 tall, radius 8, 1.5px border, size S; :active reads --bg-action-pressed, :focus-visible a new --ring-focus-controlit was the only accent button in the product declared outside button.css; a pair in one row cannot round differently
6.3The header's two counters get their border back (owner's call)
border-color
transparent--line-strongБОНУСИ and КОШИК carry a number, and a number needs an edge to sit in
6.3The pager's border joins the outline finish (10 instances)
border-width
1px1.5pxthe outline finish is 1.5px solid --line-strong, one label colour and one hover
6.3Four outline forms stop being quieter than the rest (.wish 6, .btn.cd-cont 4, .btn.gh 2, .btn 1)
color
--text-secondaryinkthe label colour was secondary in five forms and nothing marked those five as quieter
6.4The text finish takes one ink (.ci-lnk 22, .pf-dangerbtn 2)
color
--text-secondaryinkcolour and behaviour only: ink, accent under the cursor, a focus ring
6.5The blocked checkout button stops holding a strong edge (.cd-blocked)
border-color
--line-strong--line-haira control that is off does not hold a strong edge; disabled is a state on the attribute, not a variant on a class
6.6The size ladder stops being a comment: 122 size declarations deleted from 20 component files, measured over 574 button instances
padding / font-size / min-height / border-radius
25 heights, 13 paddings, 5 type sizes, 4 radii set by 75 rules in 23 filesS 8/12 · 14 · min 34 · r8 · M 12/16 · 16 · min 44 · r8 · L 16/24 · 18 · min 52 · r12; heights 25 -> 18, paddings 13 -> 4, radii 4 -> 3a button is small because of where it stands, not because someone typed a smaller padding that day; the radius follows the size
6.6The checkout stops scrolling sideways at 360
grid track / min-width
11px of overflow, pushed to 51 by the size change (a 1fr track taking its floor from min-content)minmax(0, 1fr) plus min-width: 0 on the social pair and the welded field; 0 screens scroll sidewaysthe social sign-in pair could not shrink
6.6`font: inherit` on .ob-collapse silently reset the ladder's type
font shorthand
font: inherit (type back to 16px)font-family onlythe shorthand sets every font property, including the one the set had just decided
6.7The button becomes one class: 56 names -> 22 API combinations, 44 distinct renderings -> 23, 314 look declarations removed from 24 files, 798 buttons carrying the API
min-height / padding / font-size / border-radius / border-width
«Каталог» 41.4px tall with a min-height: 34 that never fired; three weights 400/600/700; the accent family split between a 1.5px border and noneS 8/12 · 14 · 40 · r8 · M 12/16 · 16 · 52 · r8 · L 16/24 · 18 · 64 · r12; every boxed finish carries the same 1.5px borderfive finishes laid over 56 bespoke names are five ways of being inconsistent; an equal 12px rung, and nothing moved more than 1.4px
6.7The last two black buttons become accent (.co-getcode, .coach-newcta)
background
--bg-inverse--bg-actionthere is no black finish in the set; two «Отримати код» had two grounds
6.7Every close becomes a ghost icon (.auth-x, .cd-x, the drawer and sheet closes)
finish / mark size
an outline box on two of them, none on the others, two different greys; one ✕ at 16one quiet mark, warm ground on hover, ✕ ink 20 everywherea close is not the action of the screen it closes
6.7The pager becomes a real icon button
box size
34px box with a 1px border plus an ::after stretching it to a 44 targeta 40 box that IS the targetthe icon finish owns the square, and a target drawn by a pseudo-element is not the control
6.7L loses side padding below 480
padding (horizontal)
2416 (-8px)giving the accent finish its border pushed «Підтвердити замовлення» onto a second line at 360; the type stays 18, the air does not
6.7Dialog footers move from S to M (.pm-f, .fsheet-foot, all 31 .btn / .btn dark pairs in _nav.js)
size class
SML is reserved for the one action of a whole SCREEN, which a dialog is not
6.8A button never wraps: eight buttons were folding their label, four of those would then have spilled
white-space
wrapping labelsnowrap; 0 buttons wrap, 0 overflow, 0 screens scroll sideways at 1280 and 360a label on two lines is not a long button, it is a button that does not fit where it was put
6.8The phone step: below 480 every size gives back one step of side air and L drops to the M type
font-size / padding at <480
L type 1816; height and vertical padding do not move18 is a desktop luxury and a label that has to be read is worth more than the air around it; the touch target is not negotiable
6.8The out-of-stock buy row stacks
row layout
«Повідомити про надходження» sharing a row with a 54px heart - buy box 371px, page scrolling sideways by 42stacked; 0 sideways scrollout of stock the action needs the whole 328px of a phone column
6.8The header's two counters are left aligned and the star becomes the honey jar (owner's call)
text-align / glyph
centred labels, a star markleft aligned from the button's left edge, an empty honey jartwo lines read as a column, and centred the button would shift as the number changes; the jar is the store's own reward shape and stands EMPTY because the header is a way in, not a rank
6.9A mark beside a word gets one ladder (17 forms, 243 instances; 11 declarations deleted from five component files)
icon ink beside a label
15, 17, 18, 19 and 21 next to the SAME 14px label, decided by five component filesS 18 · M 20 · L 24, text finish 1.15emthe button decides, on the same ladder the icon-only button already used; a leading mark is a noun, a trailing sign is punctuation
6.9The checkout's city chooser wears the set's S below 480
size class at <480
M (grew 5px of mark and stopped fitting a 247px phone column)Sa component may pick which size of the set it wears, it may not invent one
6.10Six real screens were rendering type at the size they inherited because the token did not exist (.auth-consent, .auth-sub, .bb .simple, .cd-oosnote, .cedlg p, .fullcomp)
font-size
--fs-11-5, --fs-12-5 x2, --fs-13-5, --fs-14-5 x2 - all invalid, so the declaration dropped and the text inherited (up to 4.5px larger)11.5 -> 12, 12.5 -> 12, 13.5 -> 14, 14.5 -> 14an invalid value in CSS does not fall back to something near it, it drops the whole declaration; the scale has no half rungs
6.10The header stopped jumping when a number arrived (68 counter instances across 39 screens)
min-width
96px, which sat below all four measured states (124 / 98.6 / 100 / 103)124 - the widest EMPTY state; all four states now measure exactly 124empty is the state whose width is fixed by copy rather than by data, so it is the only one that can set a floor
6.11The quiz invitation block was never a row (.goalcta on four home screens)
display / gap / margin-top
display: block, no gap, no margin (the «gap» was a space character)flex, gap 12, margin-top 16the class exists only in wireframes/_wf.css and was never carried into design/system at the step-3 split
6.11The quiz hint takes a size of its own (.goalcta .hint)
font-size / color
16 / near-black (inherited body)14 / --text-secondary.lintro, the supporting line 20px above it in the same block, is 14 secondary; two supporting lines at two sizes is noise
6.11«+ ще 11 брендів» stops shouting (.fmore, 14 places across the listing screens)
font-size / color / margin-top
16 / near-black12 / --text-secondary / margin-top 8it was rendering louder than the 14px options it extends; secondary and not tertiary, because tertiary is what an OFF control wears
6.11The quiz button steps down a size on all four home screens
size class / height / label
L - 64 tall, label 18M - 52 tall, label 16L is «the single action of the screen»; here that action is the six tiles and the quiz is the alternative
7The field becomes an atom: 89 fields onto the API, 57 look declarations removed from six component files
font-family / height / border / radius / font-size
66 of 101 fields set in Arial with pure #000 ink; nine heights (37·40·44·45·46·47·60·61·64); borders in three widths, radii in three, type in five sizes including a 15 that is not a rungheights 40 · 44 · 60 (OTP) · 80 (textarea) and nothing else; fonts Inter (74) and IBM Plex Mono (27), no Arial; ink one valuea field does not inherit font-family and three files of fourteen told it; two rungs and no third, because nothing in the product occupies one
7The notify row's field comes back onto a rung
align-items / height
stretch, making the field 64 - a height no rung of the set has, borrowed from whatever stood beside italign-items: centera field that gives up its own box takes the row's height instead of its own
7.1The select's caret becomes ours (one <select> in the product, the coach's client picker)
appearance / background-image
appearance: auto - the browser's own caret, off the ink ladder and drawn differently on every platformappearance: none, 40px of room on the right (12 padding + 20 mark + 8 gap), the icons.js chevron M6 9.5l6 6 6-6 at 1.9 round, ink frozen in --field-careton product-coach it stood 150px above OUR caret on the city chooser: two «choose something» controls with two different marks on one screen
7.2The choice menu becomes one atom for the select and the five menu triggers; sorting at 360 becomes possible at all
trigger height
the picker's trigger wore a button's padding (12/16), making the box 48 where the field ladder says 44; the mobile «Популярні ▾» opened nothing44, 16px, medium weight - a menu built FROM a field keeps the FIELD's rung; 15 menus built, every list a listboxthe sort control answered the mouse and nothing else - no keyboard, no Escape, no focus return, and on a phone it did not exist
7.3The PDP wishlist heart takes the size its class already claimed (.bb .wish)
box size
50 in the structure block and 54 in the colour block, while the element's class says 52the component declares no box at all; the heart measures 52the two concatenated blocks meant one selector was written twice in one file and the first never rendered
7.3A brand mark was setting a button's height on auth.html
flex box on .uiv-brand / vertical-align
«Продовжити з Google» 55.8 and «Продовжити з Apple» 59.6 - two identical controls 3.8px apart, both over the M rungall three buttons measure 52each mark oversizes its own svg to keep the INK equal, so the svg was the tallest thing in the button
7.5The trailing arrow stops being a typed character (34 signs)
glyph / font-size of the trailing mark
«→» U+2192 typed into the label, read aloud as «стрілка вправо»; 8 trailing marksarrowRight drawn from icons.js with aria-hidden; 48 trailing marks, each at 1.15em of its own label (14 -> 16.1, 16 -> 18.4, 18 -> 20.7)the character is part of the LABEL and a screen reader says it out loud; a mark with aria-hidden is silent, which is what a decoration owes
7.5The city chooser's caret stops being drawn twice (.dpcar deleted)
caret drawing
a typographic ▾ shrunk to 10pxthe set's chevronthe caret is no longer drawn twice
7.6The underline comes off the four profile actions (btn--inline removed)
text-decoration
underlinenone; ink stays rgb(28,28,28) at rest, hover still accent rgb(255,90,0)not one of the four is inside a sentence, so the underline was decoration the system's own rule does not ask for
7.6The arrow is addressed at the control, not at the button - the 20 signs left on links become marks
selector address / font-size / margin-left
[class*="btn--"], so mega-menu column heads, «Докладніше про програму →», «Усі покупки →», «Як це працює →» and the accordion ▾ kept their charactersa, button, summary, [role="button"]; 120 visible trailing marks at 1280 and 68 at 360, every one at exactly 1.15em; the mark takes margin-left: --space-4punctuation cannot be one size on a button and another on a link; a link is not a flex row, so on the mega-menu head the arrow landed flush against the last letter
7.8The header row unifies on 44 (136 controls across all 34 pages that have a header)
height
.wfh-actions .wfh-act height: --size-46; the search shell at 40 and its input and .go at 3744 on the actions, 44 on the search shell, 41 on its input and .go; the header 114.2 -> 112.2 and each page 2px shorter--size-46 held no other control anywhere; 44 is the finger minimum that btn--icon, field.css and menu.css all stand on
7.10«Читати більше ↓» joins the button set on four listing pages
display / text-decoration
display: inline, no underline (17px tall)inline-flex (22.4 tall, baseline unmoved), text-decoration: underlinean action written as words INSIDE a sentence is exactly what btn--text btn--inline is declared for, and this is the only true --inline in the shop
7.11Six more typed signs become drawn marks (close, plus, minus, arrowDown added to icons.js)
glyph
+ U+FF0B x408 on 34 pages, ✕ U+2715 x100, − / + x32, ★ U+2605 x15, ↓ U+2193 x4, ▦ ☰ x2drawn on the set's anatomy (viewBox 24, ink inside 2..22, stroke 1.9); 0 signs left on any controla census of a set you defined cannot find what is outside it - the earlier checks only looked for → ▾ ⌄ ›
7.16The brand-ink rule had been inert since it was written - all four brand marks drew at the same size
flex (on .uiv-brand svg)
auth.html google / apple both 20; checkout.html both 18auth 24 / 27.8; checkout 21.6 / 25; button heights unchanged at 52 and 40the svg is a flex item and a flex item shrinks by default - `overflow: visible` gave it permission to be painted outside the box, never to BE bigger; that is `flex: none`
7.16The footer's messenger marks stop being sized past the component
--brand-ink / svg width
footer.css set svg{ width:16px } while the box stayed at 1.05em = 14.7--brand-ink: 16px; box and drawing both 16, and the row did not movethe caller says how much INK, icon.css does the sum
7.17The stacked header action gets its own rhythm (.wfh-act.stack)
gap / glyph size / air
glyph 18 · gap 8 · label 12, air above 1.2 and below 1.2glyph 20 · gap 2 · label 12, air 5 above and 5 below; box still 44the gap inside the control was six times the air around it, so grouping read backwards; the 44 is not negotiable, so the air comes out of the gap
7.17«Кабінет ▾» gets its air back
caret font-size
1.15em - 13.8px in a 12px line, leaving 1px of air where «Увійти» had 5the caption's own size; measured 4.6 / 5 / 5 across the three, all boxes 44a trailing mark is right in a line of text and wrong in a budgeted caption
7.18The stacked action turns out to be one atom written twice (header .wfh-act.stack and tab bar .wf-tab)
glyph size / caption ink / caption line-height
tab bar glyph 21 (1.05em on a 20px emoji), caption --text-muted, leading 19.2 inheritedglyph 20 (a rung of the set), caption --text-secondary, flat leadinga caption under a mark is one line by definition, and a mark that leads cannot be the faintest thing in its own control
7.20Under the cursor, the caption now moves with its mark (.btn--stack:hover .lbl, .tl)
color on hover
mark #1C1C1C -> #FF5A00 while the caption stayed #5B5B54color: inherit - caption #5B5B54 -> #FF5A00, plus its own transition: color .15s; no box moved by a pixela caption under a mark is part of the control's NAME, and a name cannot stay behind while the thing it names lights up
7.21The mobile catalogue overlay stops wearing the cart row's grid (`.ci` scoped to `article.ci`)
display / padding / border-bottom / column width
.ci box 24 wide and 52 tall, child stretched to the 74px column, mark overlapping its label by -10px, 13 stray dashes, row height 85, 9 rows on a screen24 x 29, drawing at its own left, mark -> label +15px, 0 dashes, row height 62, 13 rows on a screenone name, two meanings - a cart row is an <article> in all 14 places and a mark is a <span>, so the markup already says which is which in both layers
7.21bThe same scope applied to the frozen grey twin (wireframes/_wf.css:1626), on the owner's word
display / padding / border-bottom
.ci 24 x 61, grid, 16px 0 padding, 1px hairline, mark -> label -9 overlapping, 13 dashes, row 9024 x 28, block, 0 padding, no border, mark -> label +16, 0 dashes, row 57the design system could not be right about .ci while the prototype it was split from was wrong about it
7.23The chip's four selected editions come to one, chosen on contrast (owner's call)
background / color on .on
.ptab.on accent fill + white label (3.13:1), .ord-tab.on white ground + accent edge and label (3.13:1), .cegoals button.on ink fill + white label (15.9:1)accent fill + INK label (5.45:1), the .acc-link edition - the largest family and the only accent edition that passes AAsame control, same job - press a word to choose - and six files each grown their own edition
7.23The order filter joins the chip family and the 96-instance drawer chip gets a hover for the first time
border-width / color / hover
.ord-tab 1px edge, resting ink --text-secondary, 40 tall; .dr-chip no hover at all1.5 edge (41 tall), resting ink --text-body; one hover edition - edge and word to #FF5A00a choice not yet made is not muted; four hover editions were four files disagreeing
7.24Three marks in the account rail had been drawn at 0x0 (42 hits on all seven account pages)
svg width / height
0 - `.acc-link .ic .uiv-ic svg{width:18px}` reached THROUGH a wrapper the sign-only shape does not create, so the svg fell back to 1.05em against a font-size of 0`.acc-link .ic svg{ width:18px; height:18px }` - all eight rows read 18x18a component that fixes an icon's size must size the DRAWING, not a wrapper somebody else may or may not create
7.25The mega menu stops overflowing the page in the narrow band
containing block / max-width / grid track
hung off the .wfh-cat button with max-width: 94vw measured against the viewport and a grid floor of 226 + 420 + 196 = 842; at a 900 window its right edge stood at 1155 against a page 885 wide - 255px unreachable.wfh-cat static, .wfh-main the containing block, left/right 16, max-width 940, minmax(0, 1fr); 813 wide at an 845 canvas, 0 sideways scroll at 77 checksthe product switches layouts on @media, which reads the VIEWPORT, while the product lives in a canvas that may be narrower; a floor no max-width can get under turns «narrow the panel» into «overflow the page»
7.26Four files were holding a fifth file's number - measured at a 1000 viewport
--shell-top / --shell-left (was literal 216 / 40 / 899 / 900)
auth.html .auth-ov left 216, top 0; cart.html .cart-drawer top 0 under the bar; checkout.html body padding 216 / 0left 0, top 40; drawer top 40; body padding 0 / 40 - the tokens flip at exactly 1076step 7.25 moved the shell to 1076 and every copy stayed at 899; the rule stays in the component, the number does not
7.26The chevron on the catalogue overlay's rows takes the role that names it (3 rows, two go one step darker)
--mark-faint
#cbcbcb (a raw literal in a system file, while the third row asked for var(--grey-bb))#BBBBBBthe file contradicted itself and the semantic token already exists for exactly this job - «the quiet mark: a chevron on a row»; declared as this step's one visible change
7.27The trust banner's star joins the one rating rule (4 instances, one banner)
star size
14 in a 14px row15 - calc(1em + 1px)the same row size at which the buy box and the review row both drew 15; a star's ink does not fill its box the way a digit fills its own
7.27The checkout's bonus star, the last ★ on the site painted by the font (2 instances)
glyph
typed ★drawn from the setmarks.js walks CONTROLS and this is a span in a div; the three uivStarify calls are named after ratings and a bonus is not a rating
7.27The review modal's star picker (15 instances on 3 screens)
star fill
outline, and pressing one turned it into a gold outlinefilledicons.js already states the rule - one drawing, two finishes: outline for a nav chip, filled for a rating; that path was not following it
7.28The skeleton bar becomes one height and two widths stop disagreeing (6 bars + 2)
height / width %
.co-skel .sl and .auth-skel .sl 11px, .acc-subsk 12px; .co-skel .sl.s 46%; .auth-skel .sl.m 70%10px on all of them; 50%; 72% - and the checkout and auth columns came down 2px eacha skeleton bar is not the height of the text, it is a mark saying «a line goes here», and two files disagreeing by two percent about the same grey rectangle is not a decision anybody made
7.28The pulse can be stopped
@media (prefers-reduced-motion: reduce)
missing - the one component on the site whose whole job is to moveshape stays, breathing stops, opacity settles at .78 mid-cyclea loading hint must not be the thing that makes somebody ill
7.29The language picker joins the radio's row rung (.pf-lang, 2 instances in the coach's client dialog)
padding / border-color / background
padding 16/16, resting edge --line-strong, chosen edge --line-inverse on --bg-sunken, circle 20x20padding 12/16, resting edge --line-hair, chosen edge/ground/circle on the accenttwo families of three already said the accent, and the design principle says the accent is the single action colour
7.30The login dialog's link row moves to the loud rung (.linkrow a, 6 instances)
font-weight / color / text-decoration-color
600, --text-secondary, underline in --line-strong700, --text-body, underline in ink700 on ink is what makes the loud rung legible AS a control at 12px; it was one file disagreeing with the site, not two disagreements
7.30«Змінити номер» joins it (.auth-sub a, 2 instances)
font-weight / text-decoration-color / cursor
600, underline in --line-strong, cursor: auto700, underline in ink, cursor: pointersame rung, and a link that answers a click has to say so
7.30The footer's legal row - the most repeated link on the site (87 instances, drawn by an inline style typed into a render function)
color / text-decoration-color
--text-muted, underline in its own colour--text-secondary, underline in --line-strong (the quiet rung)the rule lived in an attribute no stylesheet could reach; the wrapper gained class="wff-legal"
7.30Two checkout link families gain the underline they were only colouring (.co-consent a 2, .co-foot-links a 24)
text-decoration
text-decoration-color set and NO text-decoration - the colour of an underline that did not existthe quiet rung's underlinenot planned; the A/B found it, and both do a job the site already underlines elsewhere
7.30Four home screens carried an inline style="color:#111" that two !important were beating
color
#111 on 8 links and 32 icon marks inheriting it#1C1C1C (--strong), with the grey rule given to _wf.cssan !important is a note that something upstream is wrong; deleting the note without reading it puts the bug back
7.32The view toggle's chosen and hovered cells (14 chosen, 8 reachable)
color
chosen cell's ink white (--text-oninverse on a 10% tint); hovered cell's glyph grey - a hover on 13 screens that changed nothing you could see--text-action on both.vtoggle span matched every span inside the box including the icon's own wrapper, so two patch rules existed to take the cell's paint back off it; `>` says what was meant
7.33The tab bar's five tabs get a corner (340 rows: 5 tabs x 34 screens x 2 viewports)
border-radius
08pxthe control touched more than any other in this product returned the identical computed style at rest, hovered and pressed
7.33The burger drawer's shadow takes the token that describes its job (68 rows)
box-shadow
0 16px 34px / .13--elevation-3 (0 14px 34px / .12)the drift 7.26 measured and left, because that step already carried a visible change
7.333 351 controls that a finger touches gain a press state (chip 503, icon-text button 92, checkbox 176, stack-action 238, radio 38, stepper 15, view toggle 8)
:active background
no answer - :active appeared 5 times across 2 files, one of them a reset--bg-action-soft (#FFF9F5), or --bg-action-pressed (#E85200) where the ground is already accent; verified by real touchscreen.tap()on a mobile-first product the feedback layer had been written for the secondary device; both grounds have been in tokens.css since 5.5, named for this job
7.35The availability dot stops being typed 107 times (212 rows: `TXT: ● X -> X` on all six families)
the dot's footprint (glyph advance + space -> box + gap)
14.25px (Inter's ● at 5.16px of ink on the 12px rung, 6.02 at 14px, plus a 2.84 space)10px - a 6px drawn dot in currentColor with --space-4; .oh-status width -4.4px, .aord-status -4.4px, .oh-thumbs shifts 4.36pxa screen reader says «black circle В наявності», the glyph has no size of its own, and nothing can tell it from the word
7.35The PDP's availability line kept a font-family the atom now declares (.bbavail)
font-family
'Inter', sans-serif written in buy-box.css - dropped in the move, which put the line in monospace and 8.5px wider--font-body on the atom; width -1.8px against HEADit sits inside .bbmeta, which is monospace; the token carries the system fallbacks the literal did not
7.36The live price takes one weight at 20px (.ci-sum, .li-sum, .tnew, .mbp b - 20 elements)
font-weight
700800the live price had two weights at one size - 800 on 99 elements, 700 on 20 - and nobody chose the split
7.36The struck price takes one weight (.ci-old, .li-old, .told, .mold - 10 elements)
font-weight
500 and 600400 (--fw-regular, added to tokens.css)the struck price had three weights and nobody chose the split: .told inherited the 600 that .tprice declares for its block
7.36The ₴ kerning moves from the container to the figure, and reaches the list card at all (13 + 9 elements)
word-spacing / letter-spacing on the figure
-.24em declared on .tprice (16px) resolving to -3.84px and inherited by a 12px struck price and a 20px live one alike; the list card had nonecomputed on the figure; .lprice and .lold gain itproduct-card.css:72 lists .pcard and not .pcard-l
7.36The currency mark follows its parent (.uiv-cur, 54 elements)
font-weight
its own weightinheritthe mark is .55em of the price beside it and has to be the same voice
7.36bThe discount chip takes the mono face DESIGN-artifacts.md gives every price figure (13 chips + 2 put back)
font-family
Inter on .lcut, .hd-cut, .cut, .ci-cut, .li-cut (and .tcut, regressed to Inter by 7.36)--font-monothe cut carries a figure; the tier variant carries a word («гурт») and takes --font-body instead
7.36bThe chip stops having four heights (35 chips) and three other axes fold
line-height / font-weight / padding / letter-spacing
line-heights 16, 19.2, 15.6 and 12; .cut at 800; .tcut padded 2/4; .mcut tracking -.01em--lh-flat everywhere, 700, 2/8, no tracking; the 12px chip goes 49x23 -> 45x16 and the 10px one 43x20 -> 40x14, so a cart row is 190 -> 186a chip's height is its line-height plus its padding, and nobody chose any of the four but the last: 1.6 is the page's body leading inherited by a chip that never asked
7.37The counter beside a filter option takes the family the other 350 have (.flink .ct, 96 rows)
font-family
Inter--font-monoa count two pixels from 350 identical counts, and the only one in the body face - chip.css gave it a size and a colour and no family
7.37The product card's badges come down a line (52 rows)
line-height
1613 (--lh-snug).tag alone is not a badge; the file now names .tag.tag-pop, .tag.tag-new and stops carrying a dead white edition
7.37The status pills come onto two rungs (.oh-status 8 rows, .aord-status 2, .ci-oostag 2, .rbadge 14)
line-height / padding / background
.oh-status line-height 19.2; .aord-status padding 2/8; .ci-oostag padding 4/12; .rbadge filled with --bg-success and bordered with --line-success-soft15.6; 4/12; 2/8; one green - --bg-success-soft, whose own comment reads «the fill of the success pill»12px is the pill of a row that is mostly about the status, 10px rides inside something else; two greys under a percent of luminance apart survived because nobody could see them
7.37The list card's badge takes the family's shape (4 rows)
border-radius
4--radius-pillthe list card carried a dead white-with-a-hairline edition that started rendering the moment the atom took over, caught by the A/B
7.40A leading that step 5.6 had deleted was hiding inside a `font:` shorthand (.coachbox .cbnote)
line-height
1.55 - 20.15px1.6 - 20.8px; .coachbox grows 1.95px at 390 and 1.3px at 1280inside `font:` a leading is a slash and a number, not a property, so the 5.6 sweep could not see it
7.42The cart counter badge had three renderings of one number; the face is keyed on the class (38 rows)
background / color / box
phone icon row --bg-inverse with a white label; desktop stacked action --bg-action with ink; on the number button neither parent matched, so it rendered as a bare 9x18 run of textone accent pill: ground #1C1C1C -> #FF5A00, label #FFFFFF -> #1C1C1C, 15x15 everywhereboth editions carried the same «6» at the same moment and the width of the screen decided which one a person saw; .wfh measures #FFFFFF, so the ink edition was a dark mark on a light bar
7.42The stacked action's hover rule was never in the cascade - one stray comment closer deleted
color on hover (.btn--stack:hover .lbl, .tl)
twelve rule bodies on disk, eleven in the CSSOM - the caption of every stacked action, on the header's two buttons and the phone's five tab captions across 34 screens, did not answer the cursorthe rule parses and wins at (0,3,0)a comment closed itself four lines early and the parser swallowed the selector of the next rule; all 78 stylesheets now balance
7.42The list card's heart gets the hover the grid card's has (.pcard-l .lfav)
color on hover
no hover - product-card.css:69 pins .pcard-l .lfav:not(.on) at (0,3,0), which beats .btn--text:hover at (0,2,0)`.pcard-l .lfav:not(.on):hover` at (0,4,0), which winsbutton.css states the quiet ink and its hover on two adjacent lines; this surface carried the first and not the second
7.43The list card answers the cursor with the same sentence the grid card does (7 cards x 3 widths)
border-color and color on hover, transition-property
edge --line-strong, title nothing at all - `.pcard-l .nm` matched ZERO elements because a list card's title is `.lnm`edge --line-action, title --text-action, transition-property: colorthe largest word in a list row - the thing a finger aims at - did not answer the cursor; the edge is the card's own «this one» and the system has exactly one colour for that
7.44The product card's lift joins the nine other surfaces
transform: translateY on hover
-3px on .pcard alone-2px, which .hpromo, .hdeal, .tbn, .blogcard, .certthumb, .gthumb, .gtile, .hvert and .tsx .uiv-ic all already usednine against one is not a decision about cards, it is the sweep that never happened
7.45A product that cannot be bought fades by one value (.ci.oos - photograph, name and price, 3 rows x 3 widths)
opacity
.45.5one meaning on one kind of surface, two values in two files; two readers against one, and nothing distinguishes a dimmed row from a dimmed card
7.47A phone media block stood above the rules it had to beat, so the trust strip's icon drew its desktop size on a phone (1645 declaration-level diffs on three product screens at 360)
icon box / glyph / column / tile and strip height
icon box 44x44, glyph 23x23, text column 230px, tile 68px, strip 290px38x38, 20x20, 236px, 66.38px, 283.5px; 570 elements below the strip move up by exactly 6.5px`.tsx .uiv-ic` here and there are both (0,2,0) and the later one takes it - the later one was the 44px desktop box; the six pixels the icon gave up went to the label
7.47The counter on the cart shelf's mark takes the ink the locked rule gives a marker (10 rows each at three widths)
color on --bg-action
--text-oninverse, white on #FF5A00 - 3.13:1ink - 5.45:1DESIGN-artifacts.md says a label on an orange fill is white, and directly under it that small orange things which are NOT buttons keep the ink label; this is a counter on a marker at 10px, and it was the only exception of 18 selectors
7.48The bonus ledger's «Баланс» column could not be reached on a phone
overflow-x / position
overflow: hidden on a 328px wrapper holding a 411px table - 3px of the 87px column visible at 360 and no way to scroll to itoverflow-x: auto (scrollbar suppressed, overflow-y pinned to hidden); a real touch gesture reaches scrollLeft 85 and shows all 87; .led-head and .led-note go position: sticky; left: 0 so the title stays at +1 instead of travelling to -68the alternative is that the buyer cannot see their own bonus balance on the device the store is built for first
7.48The base loyalty tier stayed a raw colour emoji on the screen a buyer sees before their first order
`if(UIV_TIER_EMOJI[part])` -> `if(part in UIV_TIER_EMOJI)`
3 raw emoji on account-empty.html, 0 instances of .uiv-tier.t00 raw, 3 marks; the page grows 3.39px at 390 and is identical to the pixel at 1280the map sends the base tier to 0, which is falsy in JavaScript
7.51On the order's «Разом» row the label was heavier than the sum (4 figures x 4 widths = 16 rows)
font-weight
600 on the figure while .sr.total span gave both halves --fw-black800 - the pull-back declaration deletedthe row exists to state the sum; the pull-back at (0,3,1) was drawing the wrong thing
7.54The out-of-stock note inside an order had its margin upside down (.ord-oos, 4 rows)
margin
var(--space-16) 0 var(--space-2) - 33px of air above, 2px below0 0 var(--space-16) - 17px above, 16px belowthe note is the FIRST child of .ord-body, which already pays 16 on every side, and two pixels glued it to the first product line, which is not what it is about
7.59The address dialog's delete button takes the outline finish by class (3 buttons in three dialogs)
padding (horizontal) / min-height
a bare <button> with no class, drawn by hand in nine declarations here and eleven in _wf.css; side padding 16 at every width; 178x40 at 1280class="btn--outline btn--s btn": padding 12, and 8 below 480; 170x40 at 1280 - 8px narrower at 1280, 16px at 360the button now shrinks on a phone with every other button, which the hand-made edition could not do - it had no media query; the grey prototype measured 166x40 before and after
7.60F1 - an inline style on design/account-empty.html:81
padding
style="padding:20px 14px" (on no scale in the system, outranking every stylesheet)the component's own --space-24 / --space-16; the page 2022.02 -> 2030.02, exactly +8.00pxan inline style outranks every stylesheet by specificity and neither 20 nor 14 is on any scale
7.60F2 - .rk-item:first-of-type in restock-note.css matched nothing
selector / padding-top
:first-of-type - «first among siblings of its TAG», and the first DIV in the card is .ah, the header.rk-lead + .rk-item; the first restock row tightens by 10px at the top and account.html goes 2389.25 -> 2379.25, exactly -10.00the neighbouring :last-child proves the symmetry was intended
7.61The button that ends a thing wore the paint of the button that buys one - .btn--danger (9 instances on two screens, 8 elements changed)
color / border-color / background-color
three confirmations as btn--accent (white on orange); three card deletes as plain btn--outline, identical to «Редагувати» beside them; the account-deletion opener red on hover onlybtn--outline btn--danger - ink #C42B1C, edge #C42B1C, ground transparent; hover --bg-danger-soft, active --bg-danger; the text opener red at restthe loudest object the system owns was the one that ENDS a thing; not a red FILL, because DESIGN-artifacts.md bans red splashes. Six properties, zero geometry - the box stayed 140x52
7.63The eyebrow becomes one face - nine declarations moved (1412 rows on 34 of 40 screens, no RECT and no POS)
color / font-weight / letter-spacing
.wff-col h4 --text-primary rgb(28,28,28) (580 instances); .dr-lbl, .city-lbl, .acard .ah h3 --text-secondary rgb(91,91,84) (708); .ctable th, .pl-t th, .dl .dk, .bb .vlbl, .clientpick label at bold (152 rows 700->800, 12 rows 600->800); .pm-rw on .08em--text-muted rgb(110,106,98); --fw-black; .pm-rw on --ls-caps .04em (12 rows)every eyebrow labels something set at 14px or more in a darker ink, and the footer heading was the only one as dark as the content beneath it; the two tracking tokens are now two voices, .04em Inter and .08em monospace
7.64The product card was drawing a mixture of two layouts at exactly 620 (nine declarations re-spelled to the convention)
@media boundary spelling
product-card.css closed at max-width: 620 while nine declarations open at min-width: 620; the card came out 286 x 498 at that pixelmax-width: 619; the card is 286 x 553, matching its neighbour, and 600, 619, 621 and 640 are byte-identicalan overlap is not a style question, it is two mutually exclusive layouts both applying, and the only way to see it is to stand on that exact pixel
7.64The last sideways scroll in the product - product-oos.html's buy row (1947 + 258 + 1309 + 286 + 34 rows across five band widths)
flex-wrap
declared inside the phone block only, so above 479 the row could not break: +103px at 480, +63 at 520, +23 at 560, +11 at 860, 900, 960 and 1040wrap belongs to the row: 560, 860, 900, 960, 1040 clean; 480 down to +39, 520 to +19; the heart drops to a second line and the row goes 64 tall to 128a row that is allowed to break costs nothing at the widths where it fits; what remains is a wording decision, not a css one
7.64Two singleton boundaries folded into set members 40px away
@media boundary
banner.css 700, order-row.css 820720 and 860 - the .tbanners strip folds to 2 columns instead of 5 in the 700-719 band on four home screens (1947 rows), and .ob-grid to one column instead of two in the 820-859 band (258 rows)a boundary used by one file with a set member within 40px and no content reason is not a decision
7.66The type scale gains a floor and three literals fold into rungs (40 font-size rows; 2666 rows on two screens of forty)
font-size
8.5px on the list card's «Новинка» tag (x8), 11.5px on .coachbox .cbh and .cbsave (x28), 13px on .cbnote (x4)--fs-8, --fs-12, --fs-14; twelve raw declarations became sixhalf a pixel is not a step and a scale cannot hold one; product-coach.html goes 11159.98 -> 11185.56, +25.58px, and listing-list.html does not change height because the 8.5px tag is absolutely positioned
7.67Air that refused to say so, rounded DOWN to the rung (34 margin/padding/gap rows; 2290 rows on two screens)
margin / padding / gap
18, 20, 14, 10, 26, 5 in the reassurance banner and on the out-of-stock back link16, 16, 12, 8, 24, 4every one stood one to four pixels above a rung, so the rule is round down - one rule instead of six taste calls, and the panel gets calmer rather than louder. product-oos 4084.77 -> 4082.77 (-2.00), product-reviews 3927.48 -> 3922.48 (-5.00)
7.68Five boxes that frame a product photograph become square (11 171 rows; 54 page x width pairs moved and none grew)
aspect-ratio / height
.pcard .ph 10/11 (82 instances rendering 244-246 tall), .skcard .skimg 10/11, .ci-ph 74 x 81.39, .ob-line .ph 52 x 56, .oh-thumbs i 34 x 38square on the width, height free; zero boxes changed width, zero got taller; listing.html and listing-sheet.html up to -98px shorter at 1280the photographs are 2048 x 2048 and every box paints them contained, so a frame that is not square leaves uneven air; 10/11 came from wireframes/_wf.css:482 at stage 04, before any photograph existed
7.68The loading skeleton promised a shape the card does not draw, on the phone
aspect-ratio on .skcard .skimg
10/11 with no override - 171 x 188.09 at 390 against the card's 171 x 171: a 17px jump on load1; listing-loading.html moved -69px at 390the mismatch existed only on mobile, which is the one place this product is built for
7.70The checkout's own 900 boundary folded into 860 (3094 rows on nine page-widths)
@media boundary
min-width: 900 - the three checkout screens stayed one column from 860 to 899min-width: 860 - two columns, the form 444 beside the money box's fixed 360, and the band gets 410 to 584px shorter; the money box becomes sticky7.64's own rule applied to the case it skipped: one file, and 900 is the same 40px from a set member
7.78The toast's close sign was drawn by the font, because a pass that runs once at load does not cover what is built later
glyph / box
a typed ✕ - .tt-x measuring 11x22the set's mark - 15x22, and the message 4px narrower; the toast box, ground, border, radius, padding, shadow, chip and label identical at 360, 390, 720 and 1280uivChrome() runs its passes last, and a toast is built when somebody saves an address; fixed by wrapping the builder
7.8424 real brand logotypes were loading out of design/visuals/ into four grey prototype screens
<img> in wireframes markup
184 x 184 inside a 186 x 62 box, three of six overflowing at 1280, page scrollWidth 364 against a 360 viewportremoved - the place and the name in 12/700; 0 images, 0 overflow, box/text/row height unchanged at 103x62 / 134colour never lands on wireframes/, and the sweep had never opened the grey prototype in nine steps of «no sideways scroll»
7.87uivIcons walked six named element ids, so any block outside them kept the prototype's emoji
the pass's address
12 text glyphs in the client dialog, three of them visible at restwalking the body: 10 of the 12 became marks; two did not, because 🔳 and 🚚 are in no mapthe fourth hand-written list found in this stage, and the first one still costing pixels
7.88The cart drawer's foot overflowed its own row at 390 - a defect 7.86 shipped
container width vs content
the foot is 388 wide inside its padding and the two side-by-side buttons need 222 + 8 + 209 = 439, so the `1fr auto` grid walked 51px past the edgefixed; .cd-foot appears in none of the 594 container-overflow rows7.86 had asked each BUTTON whether its own text fitted and both said yes; the ROW was never asked
7.89The cart drawer's secondary action becomes a link
the foot's height
256px - 32% of an 800-tall phone219px - 27%the drawer's foot is a fixed strip on a phone and it was taking a third of the screen
7.90The cart drawer's primary is M, not L (.cd-cta and .cd-fix on design/cart.html and design/cart-oos.html)
size class / min-height
btn--l - 64pxbtn--accent - 52px; the foot 219 -> 207, 26% of an 800-tall screenthe owner's call; the empty drawer's «Обрати ціль» stays L - a different slot, centred in .cd-body, competing with nothing
7.91The drawer's secondary was still wearing btn--l after it had stopped being a button
font-size on .cd-cont
--fs-18 - on desktop the secondary link read at 18 while the primary above it read at 16--fs-16; measured at 320, 360, 390, 430 and 1280of the four things btn--l declares, the foot's own rule overrode three, so a size class that lands one property out of four is a declaration pretending to be a decision
7.92Tapping «Каталог» on a phone highlighted nothing
wfCatTabEl() selector + .catov-open in tabbar.css
`.wf-tab[href="catalog-page.html"]` - a literal href that uivFixLinks rewrites, so catov-open landed on nothing; and the accent bar belonged to [aria-current="page"] alone, so the page underneath kept its barthe tab that carries the handler; both states on one line - exactly one bar, on the right tab, open and closed«which things get X» answered by hand; the class was right, the rule reading it was right, and the element never got it
7.92The harness's top bar covered the catalogue overlay's close and back buttons
top on .wf-catov
0 - the ✕ sat at 12..40 under a 40px bar at z-index 92, and elementFromPoint at its centre returned the bar's chevronvar(--shell-top) - overlay from 40, ✕ at 52, elementFromPoint returns BUTTON.cx--shell-top exists for exactly this and four panels have read it since 7.26; this one was left out of that pass
7.93The cart drawer's foot becomes a grid, on the owner's shape - «Знижка й бонуси» moves under the word «Разом»
font-size of the sum (and .cd-total -> display: contents)
--fs-30, the hint on a line of its own; foot 207px--fs-24; foot 181px - 22.6% of an 800-tall phone (227 out of stock, 200 at 320 where the hint wraps)24 is the rung the scale already has below 30, not a number chosen here; the sum stops being the tallest thing in the foot, which is what lets the row absorb the hint. The stand's frame read 181 the moment the rule changed, without any of the four files being edited

І 29 рухів, яких не видно - мертві оголошення, правила не в тому файлі, імена без читачів. Вони тут тому, що доказ без них неповний: більшість роботи етапу не мала бути видною, і кожен із цих рядків підтверджено проходом A/B, який повернув нуль.

КрокЩо і яка зміннаБуло → сталоЧому
5.6The glyph set, anatomy and both markup builders move into design/system/icons.jsset lifted out of design/_nav.js by a regex (trash rendered as a lid with no bin)one edition in design/system/icons.jsthe design system was describing an icon the product does not have; the fix is ownership, not a better regex
6.014 dead primitives deleted (--black, --grey-11/44/55/66/dd/ec/fa, --green-200, --red-200, four scrims); primitives 51 -> 37
colour primitives
14 unread tokensdeleted, not deprecateda value that cannot be named cannot be used by accident; every one verified at zero var() references first
6.2bThe heart and the wishlist cross get a real touch target (.fav 166, .fav.on 6, .wlrm 12)
box size / position
26 box at top/right 1244 box at top/right 3the ink stays whatever the mark needs, the target is never below 44; 12 - (44-26)/2 = 3 keeps the optical centre, so nothing moves on screen and the tap area is 2.9x bigger
6.2bcart-button.css deleted and favourite.css reduced from three stylesheets in onethe same selector declared three times, each undoing the one above (30px circle, then 34px, then width:auto/border:none)one rule; the box and the target come from the icon finishonly the third edition was ever visible, so the product had a bare 26x26 mark whose stylesheet described a bordered circle
6.10The «saved» heart merged from three editions into one state in button.css (.pcard .fav.on, .pcard-l .fav.on/.lfav.on, .bb .wish.on)
colour / fill / stroke on .on
three property sets in three files, each valid only inside the card it was written forone state: an engaged mark takes the action ink and fills itselfone meaning, three property sets; the three saved hearts render identically to before the consolidation
7.4The sweep: 1038 dead declarations cut out of 49 files, 159 rules removed whole, design/system 5041 -> 4860 lines
any property declared twice under the same selector in the same file and media
571 pairs where the values differed and 467 where they were identicalone declaration eachsame selector means same specificity, so the later one always wins; proof is a computed-style snapshot of 73 pages x 2 viewports, 62 514 elements, whose diff is byte for byte the instrument's own 14 skeleton-animation elements
7.8btn--text gets a base size and five component repeats are deleted
font-size
font-size: inherit, with section-head, cart-row, checkout-form (twice) and address-card each writing var(--fs-14) by hand.btn--text{ font-size: var(--fs-14) }all 7 labelled combinations already render 14px; the stand moved (16 -> 14) and the product did not - not one text button moved by a pixel, and 92 icon hearts changed computed font-size with no geometry change
7.9The twelve rules still hooking on the legacy .btn / .dark move to their containers
flex share
`.pm-f .btn{flex:1}`, `.fsheet-foot .btn.dark{flex:2}` and nine more`> *{ flex: 1 }` on the container; `.fsheet-foot .btn--accent{ flex: 2 }`all twelve said the same thing - how a control shares a row; the container owes nothing to any class on the child. A/B: 0 elements moved, while the counterfactual against pre-7.9 moved 117
7.28b--bg-skeleton renamed to --bg-hatch and one of its three users sent to --line-hair
token name
--bg-skeleton (which painted no skeleton anywhere - all 140 measured elements came out #F2F0ED)--bg-hatch on two hatch backgrounds, --line-hair on the filter group's hairlinethe token drew two hatches and one hairline, and 217 other lines already said the right name; 48 240 elements, 0 differences
7.31The chip - 503 instances - stops borrowing Chrome's focus ring, and .ord-tab starts answering a press
:focus-visible box-shadow / behaviour
outline: rgb(0, 95, 204) auto 1px; .ptab and .ord-tab unreachable spans, .ord-tab answering nothing even to a mouse--ring-focus-control on the eight names plus the applied filter's ✕; role=tab / tablist with a roving tabindexthe chip was the most numerous control on the site and the last one still borrowing the browser's ring; A/B against HEAD: 108 310 elements, ZERO differences at rest
7.34The closed filter sheet stops being reachable behind the screen (2 100 differences, every one `visibility`)
visibility
transform: translateY(100%) only - 14 focusable elements inside a panel nobody had opened, 42 after the step's own tab stops landedvisibility: hidden with the exit delayed past the slide; 0 reachablean accessibility fix that moves nothing anyone can see is the whole point - 0 colour, geometry, type, spacing or shadow
7.38The checkbox atom stops being overwritten by a molecule; three editions of the tick become one
box size / border / tick
checkbox.css's 18px, --line-strong border and typed ✓ rendered nowhere; filter-group.css drew a 5x9 tick turned 45°; a third dead 15px edition sat in the structure blockcheckbox.css owns the control - two row rungs, the box, the drawn tick, hover, press and the focus ringfilter-group.css - level 2 - reached past its own component and restyled the atom's class by name. A/B: 0 changes on all 201 checkboxes
7.39separator.css deleted and the breadcrumb slash drawn from CSS instead of typed 47 times
content
<span class="sep">/</span> once per gap across 22 coloured screensdrawn from CSS in one place, with aria-hiddena mark that cannot exist without its parent is part of its parent; a reader was saying «Головна слеш Протеїн слеш Whey»
7.40Nine literal font stacks in four files replaced by tokens (156 rows, all inherited consequences)
font-family
'Inter', sans-serif · 'IBM Plex Mono', ui-monospace, monospace · 'Oswald', sans-serif, five of them inside a `font:` shorthand--font-body / --font-mono / --font-displaythe literal is Inter and then nothing; the token is Inter plus the system faces. The rendered face does not change - what changed is where the browser lands if Inter is not there
7.46The spec table's dead pieces removed and the definition list moved to order-row.css (19 instances)an @media (min-width: 720px) block declared twice byte for byte, a restated border colour, .dl/.dk/.dv filed under the spec tableone block, one declaration, the definition list with the order row it belongs todeleting the wrong copy of the doubled block would have moved the pack panel's gutter from 24 to 16. A/B: 0 differences, pixel-identical
7.49Two mascots re-filed out of empty-state.css, and 18 never-winning declarations left in place.uiv-bear (the SEO block's illustration, 9 instances) and .uiv-bearwrap (the trust strip's, 3) declared in the empty-state filemoved to their owning componentsneither class is declared anywhere else, so the move cannot shift the cascade. Null pass 0, difference 0 rows across 40 screens at four widths
7.50A five-name line in section-head.css named two classes that do not exist anywhere and one it never won
font-family / letter-spacing
.lh1 (7 matched, 7 won) · .seotext .h (9/9) · .wfh-logo (68 matched, 0 won) · .empty-h (0) · .estate h2 (0).lh1 stays, .seotext .h goes to seo-text.css, the two ghosts deleteda grouped selector spanning components is not a writing style, it is a way to lose a rule. Null pass 0, difference 0
7.52An order that lived in four files: the thumbnails and the order body come home to order-row.cssrestock-note.css's three-name line beating 26 of order-row's own declarations about its own tiles; 14 classes in account-shell.cssone file describing the component whole; 14 classes moved 15 imports earlier, two names back from a file 5 imports latera grouped selector spanning components loses rules. Null pass 0 rows, difference 0 rows
7.55.pmini re-filed from gallery.css to product-card.css, and a dead media declaration removed
top (min-width: 860px)
120px declared thirty lines above 88px under the same condition - it had never drawn a pixel88px only (both editions restored at 7.57, in their original order)five of .pmini's nine rules do nothing but re-lay a .pcard. Null pass 0, difference 0
7.62A line weight the system believed in and never drew - swept in 33 declarations across 23 stylesheets
border-width
1.5px1px, plus the rule in tokens.css: two weights, hairline 1px and heavy 2pxChrome resolves 1.5px to a used value of 1 before layout runs; a census of every non-zero border on the 40 screens returns 1px (34 262), 2px (440), 4px (16) and 1.5px zero times. Null pass 0 rows, difference 0 rows
7.65The fifth weight was four all along (22 836 rows on 39 of the 40 screens, every one the computed font-weight)
--fw-black
800700every page requests Inter:wght@400;500;600;700, there is no 800 face, and Chrome falls back without synthesising - the same 12px string measures 227.656px at 700, 800 and 900. Zero visible change; 108 rows carry a 0.09px rect, which is how Chrome rounds the box
7.6955 colour declarations that restate the structure block removed from 21 files
border-color and the other restated colours
the colour block restating a colour the structure shorthand already set from the same tokenthe colour block says where the coloured product DIFFERS from the grey prototypethe structure side names a colour 328 times and only 54 are restated - the habit covers 16%, so it is not the record of provenance it was taken for. Null 0, difference 0 rows
7.7117 declarations inside a @media that restate the base they sit under, in 8 files
assorted (line-height, margin, padding, gap, border-radius, font-size, background, align-items, left)
declared again inside a query at 479, 559, 619, 639, 720, 860 and 959deleted; buy-box.css left with an empty query and a written reasona query that changes nothing reads as a decision about that width and is not one. Null 0, difference 0, and every band is inside the census widths so the zero is real
7.73Two rules keyed on a Ukrainian aria-label string replaced by :has(img)
selector / width / margin
section[aria-label="Результати"] and [aria-label="Помилка"], byte-identical apart from 126/118 and --space-8/--space-4.empty .ei:has(img) at 118 and --space-4, with .ei--wide keeping 126 for the thirdthe label was standing in for one plain fact - this illustration contains an image. A/B on the product: null 0, difference 0; the stand's own demo fell 126 -> 118 and was given .ei--wide in the same step
7.74168 non-standard apostrophes (U+02BC and U+2019) replaced in 34 files
apostrophe character
U+02BC / U+2019 inside Ukrainian prose'CLAUDE.md names one apostrophe form. Difference 0 rows - but the first sweep broke wireframes/_nav.js (a bare apostrophe inside a single-quoted JS string), which stopped all 40 coloured screens building and returned 211 471 rows
7.75.frange - the file drew a price-range bar and then wiped it four lines down (22 declarations)
content / display / background / border-radius
the grey picture plus two rules switching it off for .uiv-sliderboth halves removed - the drawing and the eraser; wireframes/_wf.css keeps its copy, where the picture IS the controlevery .frange in the product carries uiv-slider always and none ever renders as itself; a line that cancels its own line is the trace of a move that was not finished
7.76The look of the description image lived in a script, and the stylesheet read as false (.pd-img, 16 instances on two screens)
background-size (and border-style, background-position, background-repeat)
the stylesheet said center/contain and the script wrote `auto 84%` inline - contain never drew on any screenthe four look properties in desc-block.css, only backgroundImage left in the scriptis the inline value DATA or LOOK; the products ship with studio air around them and filling the box edge to edge crops it away. No pixel moved
7.79Two stylesheets were writing words a screen reader says out loud
content
cert-thumb.css «PDF» announced as «переглянути сертифікат (PDF) PDF»; badge.css `★` announced as «фото ★ ПОПУЛЯРНЕ»content: "PDF" / "" - the alternative-text form, verified property by property as touching no pixelgenerated content goes into the accessibility tree; of eight stylesheets that draw a string with content, exactly two are spoken
7.86footer.css:38 declared a transition for an arrow the footer does not draw
transition on .fh .ar
matched 280 elements and won on none of them - all 280 sit inside .fgroup, where filter-group.css says the same thing 20ms longer with one class moreremoveda declaration in the wrong file, invisible on screen, visible only to the solver
Четвертий список: що зрушило 13.08.2026, і чим це зміряно

Пак вимагає, щоб кожна піксельна різниця пояснювалась рядком з іменованого списку. Три списки етапу - зведений дрейф, правки з рев'ю основ, переведення локальних перевизначень - закриті вище. Цей четвертий з'явився 13.08, і він зміряний, а не перелічений: node tools/proof.mjs --against HEAD зняв робоче дерево проти останнього коміту й назвав елемент під кожною різницею. 19 екранів із 40 зрушили, 21 не зрушив, і найгучніший із тих, що не зрушили, дав 0.066% - тобто підлога шуму справді біля нуля.

Що зрушилоЕлемент, названий приладомПричина
Фото товару й мініатюриimg < div.gmain, div.gthumb, a.ph < article.pcard, a.lph, a.ci-ph, div.li-imgСім правил mix-blend-mode: multiply знято, шість PNG отримали альфа-канал (tools/key-alpha.py). Різниця - «помножено на майже білу плиту» проти «альфа над тією ж плитою». Найбільший рух на product-oos: 2.07%
Перша промо-плитка головноїspan.hps < a.hpromo, a.hpromo, a.hvert--text-onphoto .72 → --text-oninverse-muted .66. Роль --text-onphoto видалено: її «фотографія» була суцільною плитою
Смуга стенда над сторінкоюbutton.uiv-topbar, svg в нійЦе хром стенда, не продукт, і він у кадрі. design/_stand.css: дев'ять сирих rgba(255,255,255,.x) зведені у п'ять парних --stand-* змінних, бо плита під ними перевертається разом із темою

Чого в цьому списку немає, хоч того дня його зробили: 25 екранів тренера (110 із 119 замін - роль замість літерала того самого значення, нуль пікселів; решта 9 - на екранах, яких у цих 40 немає), іконка dna (перемальована, але жоден із 40 екранів її не показує на першому екрані) і темна тема цілком (ці 40 знято у світлій).

Чотири знімки, на які досі не посилалась жодна сторінка

design/kit/screens/ тримає kit-360-before/after.png і kit-desktop-before/after.png - design/kit/kit.html на всю висоту, 345x10952 і 1265x5162, до й після переїзду етапу 08 на system/index.css. Знайдено 14.08 пошуком по репозиторію: на них не посилається жоден html і жоден md. 2.7 МБ доказу, який ніхто не міг побачити, - а правило проєкту каже, що артефакт без видимого місця не існує для того, хто ухвалює рішення. Ось воно, це місце.

Що вони доводять і чого не доводять

kit.html це заморожений смоук етапу 07: єдина сторінка, яку tools/theme.mjs тримає поза предметом за родом, і вона не входить у ці 40 пар вище. Тож ця пара - єдиний доказ про неї, і доводить вона рівно одне: переїзд на system/index.css не зрушив вітрину етапу 07.

Сказано вголос: вони зняті 06.08.2026 і з того часу не перезнімались, тобто вони старші за код так само, як були старшими ці 40, поки їх не перезняв tools/proof.mjs 13.08. Прилад їх не бере: він читає рамку з proof/*-before.jpg, а це перший екран 390x844, тоді як тут - сторінка на всю висоту у два різні кадри. Перезняти їх тим самим приладом - окремий крок, і він названий тут, а не забутий.

ФайлЩо на ньомуРозмір
kit-360-before.pngвітрина 07 на 360, до переїзду345x10952
kit-360-after.pngвона ж, після345x10952
kit-desktop-before.pngвітрина 07 на десктопі, до1265x5162
kit-desktop-after.pngвона ж, після1265x5162
Етап 09: патерн, і доказ, що він нічого не зрушив

Етап 09 не малює нового. Він забирає композицію, яку продукт повторював руками під 53 різними іменами контейнера, у файл рівня над компонентом - і мусить довести, що після цього не зрушив жодного пікселя. Нижче доказ і межі доказу.

Що зробленоЧислоЧим заміряно
Патернів заведено1 - action-row, 4 правила, 3 класи, 0 кольорових оголошеньtools/pattern.mjs по 142 сірих і 88 кольорових екранах
Імен контейнерів переведено13 у 10 файлах компонентівперелік у patterns/action-row.css, файл за файлом
Кольорових екранів переведено15клас actions у розмітці, перелічені поіменно в інвентарі
Композиція стоїть узагалі70 сірих · 58 кольоровихтой самий лічильник; це інший замір, ніж 15, і 43 екрани, що лишились, - це етап 12
Правил вживання виведено9 (U1-U9), у кожного заповнене «звідки взято»той самий прохід, лише навпаки: патерн - те, що сталось 3+ рази, правило - те, що не сталось жодного
Підпунктів «Обмеження» доточено27 сторінок компонентів + сторінка патернагреп по design/kit/*.html
Кандидатів у патерни51 композиція на рівно двох екранах, 8 найближчих показані поіменноpatterns.html, блок кандидатів
Рядків у беклозі системи5 списків, останній - тест самодостатностіdocs/backlog.md, видимий секцією на why.html

Піксельний доказ: 15 з 15, найгучніший 0.000%

node tools/proof.mjs --against HEAD - робоче дерево проти c07e2c8, обидві половини знято в одному браузері підряд, з двох серверів: один на робочому дереві, другий на git archive базового коміту, розпакованому поза репозиторієм. На диск не записано нічого. Поріг: піксель зрушений від різниці 12 на канал, екран - від 0.1% зрушених. Жоден із 15 не дав різниці взагалі. Геометрію того самого переведення окремо переміряв tools/tree-diff.mjs на 360 і 1280: кожен елемент, його бокс і 46 властивостей.

Пари знімків у design/kit/screens/ для цього етапу НЕ складено, і це навмисно

Пак просить пари «до / після». Збережена пара для цих 15 екранів потребувала б «до», знятого в тому самому середовищі, - а десять із них узагалі з'явились аж на 8.48 і базового знімка не мають. Режим --against знімає обидві половини живими і не пише нічого, тож він сильніший за збережену пару рівно там, де пара найкрихкіша: він не може розійтись із деревом. Що втрачено натомість: людина не може подивитись на ці дві картинки очима - лишається число.
Критика етапу 09 класами, статус на кожному рядку

Два прилади незалежно, дедуп після того, як обидва набори лягли поруч. 28 підтверджених, 5 знято при верифікації. Знято - лишається видимим, інакше повернеться наступного разу тими самими словами.

КласЗнайденоХтоСтатус
Число, що розійшлось із деревом9Codex + inventory.mjsзакрито - три підсумки рівня, підсумковий абзац і друге видиме місце переписані приладом, не руками
Власна арифметика файла патерна4Codex + Claudeзакрито - 34+19, 13 контейнерів, 11+2, і чому 58 не дорівнює 15
Дірка в приладі3Codex дав вхід, діагноз Claudeзакрито - links.mjs тепер питає src, proof.mjs доводить екран без збереженого знімка, inventory.mjs питає підсумки
Розсинхрон стенда з продуктом2Codex + Claudeзакрито - ряд брендів на стенді тепер той самий, що на home-buyer
Застаріле твердження5Codex + Claudeзакрито - DESIGN.md більше не називає видалений kit.css адресою чинного значення - ні в шапці, ні в лінії значень, ні над таблицею кольору, - і «one orange per view» замінено на U8
Мова1 (5 місць)Codexзакрито
Правило без свого «Обмеження»1Codex дав вхід, бік правки Claudeзакрито - правити треба було колонку U9, а не сторінки
Підпис анатомії без класу61 із 409Claude, браузеромвідкрито - 2 мої виправлені, решта чекає рішення
Стан, що рухає розкладку0Claudeчисто - і перший нуль був хибний: mouseover подією CSS-:hover не вмикається
Роль без пари в темній темі0 із 94tools/theme.mjsчисто - у кожної семантичної ролі є обидві половини, і жоден компонент не читає колірний примітив напряму
Чорнило, що провалює своє тло в темній35 форм під 4.5:1, з них 34 провалюються і в світлійtools/theme.mjs, 276 з 280 сторінок1 дірку відкрила саме тема - .hptag першої промо-плитки головної, 5.45 світла проти 2.97 темної. Пара в ролі є; провалюється ПОВЕРХНЯ, на яку роль лягла. У беклог списком 6, бо це рішення про значення

Другий прогін таксономії по відремонтованих файлах - і він зловив ремонт

Codex read-only, вузько по 16 файлах, змінених ремонтом: 8 знахідок. Три з них - це помилки самого ремонту, і саме заради них цей прогін існує. Найважливіша: сторінка вище стверджувала «DESIGN.md більше не каже, що читає видалений kit.css», а DESIGN.md:26 і :18 досі казали - виправлена була шапка, не решта файла. Друга: розширення коментаря в action-row.css зробило застарілим число «78 рядків» у двох місцях, які ремонт же й написав. Число прибрано звідусіль: файл на 80% коментар, тож «4 правила, 3 класи» це те, що не дрейфує. Знято при верифікації - 3: три входження довгого тире в docs/decisions.md це цитата самого знака в записі рішення про нього - «дефіс у реченні, середнє тире діапазон, довге ніде». Прибрати знак звідти означало б зробити запис рішення нечитним. У всіх 281 сторінках продукту accept дає em=0.

Знято при верифікації - 5, і три з них через мою власну постановку

kit.html · kit/overview.html · design/overview.html «без реєстру» - усі три мають рядок у кореневому /_nav.js; питання Codex називало лише локальні реєстри, і він чесно виконав написане. index.css без @import - це точка входу. .field-grp > .field:hover{ border: none } - елемент уже без рамки в спокої, тож правило нічого не прибирає й нічого не зсуває.
Третій прилад: контракт етапу як чек-лист

Claude із браузером і Codex по джерелу читають те, що існує, тому пропущений гейт не бачить жоден: кроку, який не відбувся, немає в жодному файлі. Цей прохід питає не артефакт, а процес - рядок за рядком «Вхід і вихід», гейти й «Готово, коли». Таблиця стоїть окремо від таблиці дефектів навмисно: чек-лист, у якому ніколи не буває «не зроблено», проходять формально.

Рядок контрактуСтанЧим доведено або чому ні
Гейт входу перед кроком 1зробленоусі названі файли перевірені на наявність до першого кроку
Лічильник по сірому корпусу, доказ по кольоровому, обидва числа названі окремозроблено70 сірих / 58 кольорових проти 15 переведених - розведені на 9.6, доти друкувались як одна пара
Патерн існує від трьох названих екранівзроблено1 патерн, 15 екранів поіменно; 51 кандидат із двома входженнями лежить окремо, 8 показані
Патерн не заводить власних стилів; @import після компонентівзроблено0 кольорових оголошень; index.css - патерн останнім рядком
Правило переїхало (вирізано), а не скопійованозробленоCodex, клас «copied instead of moved»: нічого
Заборони виведені тим самим проходом, у кожної «звідки взято»зробленоU1-U9, колонка заповнена в кожного; Codex, клас «rule without a source»: нічого
Заборона живе у двох видимих місцях при одному авторізробленорозділ I на architecture.html + «Обмеження» на 27 сторінках компонентів з лінком назад
Екран кроку 5 пройдений по правилах поіменнозробленоU1-U8 виконано, U9 порушено - і порушення віддане системі, а не залатане на екрані
Кольорові екрани переведені, вигляд не змінився ні на піксельзроблено15 з 15, 0.000%, робоче дерево проти c07e2c8
Пари скрінів у двох в'юпортах лежать у design/kit/screens/свідомо пропущено10 із 15 екранів базового знімка не мають узагалі; режим --against знімає обидві половини живими і не пише нічого. Причина написана на цій сторінці, а не замовчана
Патерн без кольорового входження названий окремим рядкомзроблено.sys-acts - нуль кольорових, названий у файлі патерна і в беклозі
why.html зібрана, несе роадмеп-сайдбар, зареєстрована в кореневому реєстрізробленорядок «Чому саме так» у групі «Дизайн-система», done: true
references.md прочитаний і використанийзробленоплейт D і таблиця «що взято / що НЕ взято» по трьох референсах - на why.html
Правило внеску в чотирьох місцяхзробленоarchitecture.md розділ J + кореневий CLAUDE.md + design/system/CLAUDE.md + DESIGN.md
Тест самодостатності на реальній сторінці продуктузробленовузол 2.2 «Ціль-колекція», база + три стани; штатна гілка, тож IA не чіпалась
Екран зібраний чисто з системи, брак названий, а не домальованийзроблено0 приватних стилів на чотирьох файлах; беклог, список 5, не порожній
Кожен md етапу видно в браузерізроблено на 9.6inventory.md не мав видимого місця весь етап - секція «Інвентар» на overview.html з'явилась аж тут, і саме в ньому знайшлись три застарілі підсумки
Секція етапу 09 на pixel-proof.htmlзробленовище на цій сторінці
/impeccable audit і критика двома приладами, знахідки верифіковані перед правкоюзроблено28 підтверджених, 5 знято при верифікації і лишились видимими
Після правок таксономія пройдена вдруге по зачеплених файлахзробленодругий прогін Codex по файлах, змінених на 9.6
Переїздів не було, wireframes/ не змінився жодним символомзробленоgit status wireframes/ - 0 змін; теки design-system/ немає
Ритуал закриття, README = Done, done: true у кореневому реєстрізробленозаписано після «го» власника, не раніше. CLAUDE.md лишився 200 з 200: нові правила зайшли, витіснивши другу копію jtbd.md і personas.md, двоє приладів, названих поіменно замість індексу в tools/README.md, і видалений kit.css у лінії значень. Заразом у таблиці README знайшовся брак цілого етапу - Розкотки, яку її ж власна проза називає дванадцятою; тепер вона є і в таблиці, і в реєстрі

Рядок «свідомо пропущено» - це і є ідл-контроль

Чек-лист, у якому все зелене, не перевіряв нічого. Пропущене названо разом із причиною, а не переформульоване так, щоб стати зробленим. Рядок «не зроблено» тут був рівно один, ритуал закриття, і він закрився записом, а не переформулюванням.
Чого цей доказ не доводить

Сказано вголос, бо доказ, який не називає своїх меж, доказом не є

  • Дві ширини, не всі. 390 і 1280. Смуги між ними ловили окремі проходи - на 720 і на 620 знайшлись дефекти, яких на цих двох немає, - і на цій сторінці їх не видно
  • Перший екран, не сторінка. Знімок обрізано на 844px. Те, що нижче, заміряно числами, але не показано
  • Спокій, не рух. Драйвер зупиняє анімації, щоб знімок був відтворюваним. Про рух цим приладом не можна сказати нічого, і це відомий його борг
  • Кольоровий шар, не продукт цілком. 40 екранів із 142 сірих. 42 екрани тренера кольору не мають зовсім - тож ця сторінка не доводить нічого про потік первинної аудиторії. Це A13 у листі рішень і воно чекає на власника
  • Один екран із сорока не повторюється. checkout-loading дає 0.16% то в один прогін, то в інший: це стан завантаження, і він міняється сам із часом. Прилад чекає, доки сигнатура сторінки (висота документа, висота смуги стенда, кількість svg) не завмре тричі поспіль - решта 39 після цього збігаються від прогону до прогону
  • Набір 06.08 не порівнянний із цим. Умови тієї зйомки ніде не записані, тож старі «після» лишились у git-історії й ніде більше. Цей набір знято наново цілком - обидві половини
  • Стан спокою, не стани. Ховер, фокус і натиск заміряні окремими проходами; тут - те, що людина бачить, доки нічого не робить

Що ця сторінка таки доводить: на кожному з десяти тверджень число з правого боку прийшло з того самого браузера, що й число з лівого; жодне з них не набране рукою; і кожен рух у таблиці має крок, змінну й причину. Там, де етап помилявся - а він помилявся, і шість рядків листа рішень довелось перечитати наново, - помилку знайшов замір, а не пам'ять.

Етап 11: рух, і те, що жоден скріншот тут не доказ

Скріншот показує КАДР, а не рух, тому головним приладом цього етапу є обчислений стиль: 280 сторінок, обидві ширини, кожен елемент плюс його ::before і ::after. Пари кадрів нижче - ілюстрація, і так і підписані.

Різних тривалостей у продукті
12→4
Було .15s .14s .12s .22s .18s .16s .2s .25s .28s .9s 1.1s і 0s. Стало рівно чотири, і всі чотири це токени: 150 · 220 · 330 · 1100. Заміряно обчисленим стилем на 280 сторінках, а не переліком по файлах.
Кривих, яких ніхто не обирав
817→0
ease - значення, яке оголошення отримує, коли криву не назвали, - стояло на 817 з 818 резолвлених функцій. Тепер три криві розв'язані з родини power_.out приладом ease-fit.mjs (похибка 0.19-0.36%), плюс linear для циклу. Єдиний ease, що лишився, - на design/overview.html, оголошеному винятку.
transition: all
1→0
Одне оголошення в тоста розкочувалось на 32 елементи й анімувало те, чого ніхто не замовляв.
Переходів, що анімують РОЗКЛАДКУ
4→3
Три перемикачі переведено з left на transform, і хід став відношенням: 44 - 20 - 3*2 = 18, тобто рівно 21 - 3. Лишились три, усі оголошені: max-height шапки (жоден transform місця в потоці не звільняє) і дві в стендовому хромі _stand.css, який не є продуктом.
Анімацій, що підкорялись reduce
0→5826
І ліва цифра - головна знахідка етапу. Механізму не було: під *{ transition: none !important } у base.css усе показувало нуль незалежно від того, чи читає воно токен. Сітку знято, і аудит без неї спершу дав 96 дефектів, а після їх закриття - 0 із 5826.
Значень у міждокументному переході, які хтось обрав
0→5
Гілка B купувала МЕХАНІЗМ, а криву й тривалість браузер підставляв свої: 250мс ease на всіх п'ятьох анімаціях кросфейду - те саме ease, заради видалення якого етап існує. Перепис цього знайти не міг: анімації живуть на псевдоелементах, яких у документі в спокої немає. Тепер 330мс плюс крива за напрямком, і зняте зсередини живої навігації режимом motion.mjs --view.
Поверхонь, що вміють приходити
0→20
Кожна поверхня продукту з'являється перемиканням display, а це дискретна властивість: у неї немає середини, тож перехід не бачить її взагалі. @starting-style і allow-discrete стояли на нулі. Двадцять першу - панель спліт-в'ю через hidden - порахували рукою і сказали це вголос.
Таблиця за ролями: одна роль - одне число

Групування і є прилад. У файлах 150 на одному компоненті й 220 на сусідньому виглядають однаково; в одній колонці під однією роботою видно, що продукт зібрано з різних систем. Роль береться з колонки «Рух» в inventory.md, а не вгадується з числа - інакше перевірка була б круговою.

РоботаФайлівТривалості, що справді рендерятьсяБуло до етапу
відповідь32150ms, і більше нічого150 · 140 · 120 · 180 · 160 · 200 · 220 - сім різних чисел на одну роботу
зв'язок5220 (акордеон) · 330 (поверхня)переходу не було взагалі: одинадцять організмів зі станом open з'являлись в одному кадрі
статус11100ms1.1s і .9s літералами у трьох файлах
відповідь · зв'язок4150 · 220 · 330файли, що несуть обидві роботи; кожне число належить своїй
поза компонентом10-12150 · 220 · 330 · 1100стендовий хром, роадмеп-панель, оголошений виняток overview.html і власні демо цієї вітрини

Заміряно двічі й на двох ширинах, і 360 звірено, а не намічено: clientWidth дорівнював рівно 360 на всіх 280 сторінках, і жодна не дала горизонтального скролу. Обидві ширини дали ту саму четвірку тривалостей - тривалість від ширини не залежить, а от напрямок і амплітуда залежать, і саме тому обхід іде в двох.

Критика класами: хто знайшов і чим це закінчилось
КласЗнайденоХто знайшовВиправленоЗнято при верифікації
СТРАХУВАЛЬНА СІТКА, ЯКОЇ «НЕ БУЛО»1Claude, крок 51 - знято з base.css, і аудит одразу почервонів на 96–
МОМЕНТ БЕЗ prefers-reduced-motion96 елементів у 5 місцяхобчислений стиль5 із 5–
КОРПУС, ЯКОГО НЕ БАЧИВ ПЕРЕПИС1 (design/_stand.css, 91 сторінка)Codex + обчислений стиль1 - заведено окремий корпус harness–
ЛІТЕРАЛ ПОВЗ ТОКЕН2 (linear на рядку видимості)Codex2–
ПІВ МОМЕНТУ АНІМОВАНО, ПІВ - НІ1 (transform не в списку .btn, а btn--lift його міняє)читач1–
СТАН БЕЗ ВІДПОВІДІ1 (картка клієнта: ховер і вибір без переходу)читач1–
АНІМАЦІЯ БЕЗ РОБОТИ1 (scroll-behavior: smooth з етапу 07, роботи не названо ніде)читач1 - робота названа ЗВ'ЯЗОК, закрито при reduce поіменно–
ВЕРДИКТ БЕЗ ПРИЧИНИ33 рядки інвентаря з голим «–»Claude + читач (прочитав «–» як «руху немає» і не зміг сказати чому)33–
ДУБЛЬ ПРАВИЛА В ДВОХ ФАЙЛАХ1 (два обертуни)Codex–відкладено з причиною: злиття потребує спільного класу в розмітці, а розмітку одного з двох пише заморожений корпус. Рядок у backlog.md, закриття на етапі 12
ДУБЛЬ: пари fade-in/fade-out у 12 файлах12Codex–знято при верифікації: це не дубль правила, а техніка на КОЖНУ поверхню - двадцять поверхонь мають двадцять власних селекторів, і спільного місця для них немає
ЗАБОРОНЕНЕ ТИРЕ В md1Codex–знято при верифікації: символ стоїть усередині речення, яке ЦИТУЄ заборону; typo.mjs тримає його в списку оголошених цитат
ДОРОГА ВЛАСТИВІСТЬ (малювання)24Codex + Claude–винесено власнику й вирішено: усі 24 тригери це вказівник, фокус або клас вибору - одночасно перемальовується один елемент. Місце, де рухається пів документа, знайшлось інше: зміна теми, 463 елементи, закрито заслінкою
ЗНАЧЕННЯ, ЯКОГО НІХТО НЕ ОБИРАВ5 анімацій (250мс ease на кросфейді між документами)impeccable critique, крок 65 - усі три кореневі псевдоелементи переведено на --dur-slow плюс крива за напрямком–
ПРИЛАД, ЩО НЕ БАЧИТЬ СВОГО КЛАСУ1 (перепис читає елементи; перехід живе на псевдоелементах під час навігації)impeccable critique, крок 61 - режим motion.mjs --view, фальсифікований зняттям перевизначення–
СПАДКОЄМНІСТЬ ЕЛЕМЕНТА В ПЕРЕХОДІ1 (view-transition-name: 0 оголошень)impeccable critique, крок 6–відкладено з причиною: ім'я мусить бути унікальним у документі, лістинг малює 12 карток, і 12 дублікатів змушують Chrome пропустити перехід ЦІЛКОМ. Унікальні імена не можуть прийти ані з компонента, ані з файлу екрана. Рядок у backlog.md, закриття на етапі 12
«LINEAR» ЗАМІСТЬ «EASE» У ВЛАСНОМУ ЛОЗІ1Claude, при повторному знятті1 - виправлено в лозі критики, у motion.md і в base.cssвласна помилка, не знята: CSS-анімація пише криву двічі - linear на ефекті (дефолт) і справжню на кожному кадрі. Перше зняття взяло ефект. Знахідка від цього СИЛЬНІШАЄ, бо ease - головний дефект етапу
transition: all · will-change · рух у файлі екрана · токен без читача · цикл без reduce · wireframes/ змінено0 коженCodex–нуль - це теж результат, і він названий числом
Третій прилад етапу 11: контракт як чек-лист

Два прилади вище читають те, що існує, тож пропущений гейт не бачить жоден: кроку, який не відбувся, немає в жодному файлі. Ця таблиця стоїть окремо від таблиці дефектів навмисно - пропущений крок це не дефект артефакту, і змішування двох таксономій ховає його вдруге.

Рядок контрактуСтанЧим доведено або чому ні
Перепис ПЕРЕД інвентарем, з джерела І з виходу; головні числа названізроблено12 різних тривалостей -> 4 · ease на 817 з 818 -> 0 · 279 сторінок обчисленим стилем, не самим grep-ом
Інвентар моментів з ДВОХ корпусів, рівно одна з трьох робіт на кожен рядокзробленоB1 - екрани й флоу (зв'язок, статус); B2 - реєстр станів 08 по всіх 85 рядках (відповідь). Рядків без роботи: 0
Кожен момент має НАЯВНИЙ стан; список «потрібен стан» став замовленням або лежить у беклозізроблено26 компонентів без жодного інтерактивного стану, перелічені в B2. Жодного домальованого .is-hover
Референси лише на вже названі моменти, максимум три; жодної тривалості з референсузробленотаблиця C, 3 моменти, колонка «що це дає роботі» заповнена на кожному; криві розв'язані ease-fit.mjs, а не взяті з референсу
Рев'ю саме на кроці 2, до компонентівзробленотокени показані й ухвалені до того, як їх прочитав перший компонент
Три тривалості й три криві; четверта пара - окремим рішенням із рядком інвентарязроблено150 / 220 / 330 плюс --dur-cycle 1100 і --ease-cycle, ухвалені на кроці 4 з переписом по ІНСТАНСАХ, а не по оголошеннях
Жодного літерала тривалості чи кривої у файлах компонентів і патернівзробленоперепис: 0 у продукті. Те, що лишилось, - оголошений виняток overview.html, стенд і заморожений корпус
transition: all немає нідезроблено1 -> 0 (тост, розкочувався на 32 елементи)
Анімуються лише transform і opacity; дороге малювання дозволене поіменнозробленорозкладкових 4 -> 3, усі три названі; 24 малювальні перевірені по тригеру - усі одноелементні. will-change: 0
У design/*.html немає жодного transition, animation, @keyframes; заборона у двох місцяхзроблено0 у продуктових екранах; architecture.md розділ «Внесок у систему» + design/system/CLAUDE.md (вкладено в правило 7, а не одинадцятим рядком)
Однакова роль - однакова тривалість, доведено ЗГРУПОВАНОЮ таблицеюзроблено32 файли з роботою ВІДПОВІДЬ рендерять 150 і більше нічого; до етапу на цю роботу було сім різних чисел
Обхід у ДВОХ в'юпортах, 360 ЗАМІРЯНИЙзробленоclientWidth === 360 на всіх 280 сторінках, горизонтального скролу 0
Блок prefers-reduced-motion, і жодного значення більшого за 1msзроблено5828 рухомих елементів, з них при reduce понад 1ms: 0. Перший прогін дав 96 дефектів у п'ятьох місцях
Цикли при reduce замінені СТАТИКОЮ, а не прискоренізроблено3 з 3 (.skpulse, .auth-spin, .co-spin), кожен зі своїм статичним станом. 1ms на циклі - це миготіння, тобто гірше
Скорочення руху не скасувало жодного станузробленоусі 20 поверхонь приходять і при reduce; зникає рух, а не поява
Страхувальна сітка на * - остання, і перевірка зроблена з нею вимкненоюне ставилиі це головна знахідка етапу з іншого боку: сітка вже стояла з етапу 07, а мій власний запис кроку 2 казав, що її немає. Її ЗНЯТО, аудит одразу почервонів на 96, і нова не ставилась. Заслінка теми - не сітка: вона живе 16мс і нічого не ховає
Тон анімації звірений з мікрокопі ПОЕКРАННОзробленотаблиця чотирьох величин проти рядка тексту; знайдено й закрито 3 розбіжності, одна з них правкою тексту із синком у microcopy.md
Патерни рухаються у своїх файлах, по одному запису на патернзроблено1 патерн на проєкті (штатна гілка 09), названо числом
Рішення про перехід між документами ухвалене ЯВНО, обіцянки, що тихо не працює, немаєзроблено, і на кроці 6 виявилось зробленим НАПОЛОВИНУгілку B ухвалено на кроці 4, але один запис купує механізм, а не значення: кросфейд їхав на 250мс ease браузера. Закрито на кроці 6, і прилад, що це питає, доведеться було написати - motion.mjs --view
Рішення про рух на точці адаптиву записане рядком, з причиноюзробленоНІ, і виняток теж НІ: усі три поверхні, яких на вузькій ширині немає, приходять від зміни РОЗМІРУ ВІКНА, а не від дії людини
Фокус не позаду рухузробленокільце фокусу скрізь на --dur-fast або миттєве; перевірено проходом табом
motion.html зібрана, у групі «Основи», приклади ЖИВІ, жодної заглушкизроблено12 секцій, усі заповнені; поверхні демонструються справжньою технікою, міждокументний перехід - справжньою навігацією
Колонка «рух» заповнена на КОЖНОМУ рядку inventory.md, кожне «немає» з причиноюзроблено33 голих «–» -> 0. Знайшов це читач, прочитавши «–» як вердикт і не змігши сказати чому
Перекличка перед КОЖНИМ раундом, раунд закритий числом N = M + Kзроблено4 раунди: 23 = 16 + 7 · 27 = 19 + 8 · 34 = 22 + 12 · 1 = 1 + 0
Ідл-контроль з обох боківзробленотокена руху без читача: 0 · рядка «зроблено» без реалізації: 0 · idle.mjs: 84 сторінки, червоних 0
Критика в ДВА прилади, знахідки верифіковані ПЕРЕД правкою, знято з причиноюзробленоClaude + Codex на кроці 6, плюс impeccable critique як третє джерело. 3 знято при верифікації, лишились видимими
Кадри «початок / кінець» у design/kit/screens/свідомо пропущеноскріншот показує КАДР, а не рух - етап каже це з кроку 1 і не має права спростовувати себе на кроці 6. Показ віддано ЖИВИМ прикладам на motion.html, які рухаються у браузері читача. У теці лишились 4 файли етапу 09
Лог критики має файл design/kit/docs/critique.mdне зроблено, і це не опискафайл, який пак називає заведеним на етапі 07, у цьому дереві не існує - і не існував жодного етапу. Шлях у прозі це ХВІСТ: у цьому дереві лог критики розв'язується у цю сторінку (таблиця класами + ця таблиця) плюс запис в docs/decisions.md. Четверта домівка для того самого тексту розійшлася б з трьома іншими
Розкотки не було: нових екранів немає, design/_nav.js не змінивсязробленоgit status: 0 змін у design/_nav.js
wireframes/ не змінився жодним символомзробленоgit status wireframes/: 0 змін за весь етап
Ритуал закриття, README = Done, wip знято з кореневого реєструне зробленочекає на «го» власника. Статус не ставиться раніше за рішення

Рядків не «зеленого» тут три, і кожен пояснює себе

Один не зроблено навмисно (ритуал чекає власника), один свідомо пропущено з причиною, що сильніша за вимогу (кадри руху), і один не зроблено, бо адреса з пака в цьому дереві не існує. Плюс один рядок, який виглядав зеленим два кроки поспіль і зеленим не був - міждокументний перехід. Саме він і є доказ, що цей прохід не ритуальний: обидва прилади читали те, що існує, а недороблена половина рішення в жодному файлі не лежала.

Голос читача не дорівнює голосу Codex - інша модель питань, інші пріори, - тож збіг із ним нічого не підсилював би, а розбіжність важить утричі. Читач дав три дефекти, яких не знайшов жоден інструмент, і всі три того класу, що існує лише між двома правильними файлами: кожне оголошення окремо правильне, і вони суперечать одне одному лише тоді, коли хтось читає обидва.

Етап 12: розкотка, і чому доказ тут не піксельний

Пари «до» ці екрани не мають за визначенням. Розкотка не переписує кольоровий шар - вона вдягає в готову систему п'ятдесят екранів, яких у кольорі не існувало ніколи. Тому питання «чи зрушило щось, чого ніхто не вирішував» тут не ставиться: рухатись не було чому. Ставиться інше - чи зібрані вони з ОДНІЄЇ системи, і чи можна це показати числом, а не переказом.

12.11 - партія 6, і остання червона брама етапу

Квіз був замовленням на компонент, а не вдяганням. Сірий екран несе 80 імен класів, система оголошувала 21. У wireframes/_wf.css немає ЖОДНОГО правила для q-*: увесь діалог живе у власному блоці стилів одного екрана, тож інвентар, виведений зі спільної таблиці стилів, не міг його зустріти - а ПОТІМ-статус означав, що його не замовив жоден агент п'яти партій.

25 із 59 відсутніх імен прочитано з драбини, а не намальовано вдруге. .q-opt - шосте ім'я на рядковому щаблі radio.css, .q-pill - третє на компактному; марки це .co-radio і .cb, підвал - три системні кнопки, рядок збереження - .field-grp, жива область - .vh. Нове: quiz.css (34 класи), .qsc третім щаблем у product-card.css, .tag-base третьою формою бейджа.

Єдиний дефект партії стояв на кроці ЗА КЛІКОМ. Підвал квіза жене документ на 68px убік на 360 і на 42px на 390 - і accept (343 екрани на двох ширинах), split і width-sweep (129 ширин) назвали його чистим, бо всі три читають документ У СПОКОЇ, де з восьми кроків видно один. tools/steps.mjs - прилад, який питає; його ж перша редакція провалила фальсифікацію (перемикач показує тіло і лишає хром неодягненим), тож він ходить КЛІКАМИ і рахує два шари окремо.

Остання червона брама закрита, і десять із 67 ніколи не були справжніми. idle.mjs звітував 67 оголошень позаду файла на 29 з 93 сторінок вітрини. Одне з них - .html, прочитане з a[href="index.html"]. Два лягають на html або body, чого коробка демо фізично не вміщає. Сім сторінки вже оголосили в KIT_STS, якого зворотне питання не читало. Решта 57 були справжні і сплачені 57 живими демо на 26 сторінках, з «винне демо» на нулі в кожному проміжному прогоні.

Головний прилад етапу - не браузер, а контракт. Один текст у design/kit/docs/rollout.md, переданий вісімнадцяти агентам дослівно, з п'ятьма підстановками на кожен запуск. Дефект вигляду коштує один екран; дефект контракту коштує двадцять, і побачити його можна лише після того, як за ним попрацював хтось інший.

Екранів у кольорі
91→141
Реєстр обох прототипів згоден: 141 сторінка (50 екранів + збудовані стани). Етап закрився на 140: лишався квіз, ПОТІМ-вузол за locked decision 2, і він стояв на карті окремим рядком із причиною, а не зникав з неї. 12.11 - партія 6 за окремим словом власника: квіз у кольорі, OUT_OF_SCOPE в coverage.mjs тепер ПОРОЖНІЙ задекларований список, і карта вперше зелена на всіх 141.
Сторінок на карті покриття
54→141
Карта була набрана руками з етапу 06 і не виглядала неповною - карта, яка ніколи не згадувала екран, виглядати неповною не може. Тепер її виводить tools/coverage.mjs з тих самих двох реєстрів і переписує розділ між маркерами. Жодне число в ній не набране.
Знаків контракту, які прилад питає
9→10
Заборона закінчувалась словами «плюс клас, якого немає в системі» від першої партії, наступний рядок відсилав агентів до screen-css.mjs, і десятого знака в приладі не було. П'ять партій «чисто» було правдивою відповіддю на дев'ять десятих речення. Знайшов Codex, читаючи контракт і прилад поруч.
Класів у розмітці без правила
24→0
101 місце у 35 файлах. 23 - інертні залишки: правило видалили на етапі 08, ім'я лишилось (coach-session.css прямо каже «.cc-repeat DELETED, all four declarations»). Одне - справжня втрата: .cmp .yes на coach-landing, три клітинки Pro перестали бути жирними, і таблиця перестала сперечатися. Правило заведене в системі, решта знята правилом.
Тег <style> · px · hex у файлах екранів
123→0
31 тегів <style> і 92 літерали px вичищено до фанауту, по всіх 91 екрані, а не лише на шаблонах. Атрибут style= зі 102 до 26, і всі 26 - оголошений виняток: відсоток на смузі є ЗНАЧЕННЯМ, бо в статичного прототипу немає сервера, щоб його порахувати. Число перевіряється, а не пропускається.
Станів головної, які рейка знаходить
0→3
Вузол 0.0 єдиний у продукті має stateFile: файл index.html, стани home-*. Ця копія пошуку загубила stateFile і будувала index-buyer.html - ім'я, якого немає в жодному дереві. Три мертві посилання на найголовнішій сторінці продукту. links.mjs цього не бачить і не міг: рейка вставляється в рантаймі.
Питань субагентів, зведених класами
0→123
18 агентів, 43 сторінки, п'ять партій. Зведені в дев'ять класів, і головне тут - пропорція: 59 зі 123 - дефекти ПРИЛАДІВ, а не екранів. Фанаут не стільки виявив, що документація тонка, скільки що перевірки під нею питали половину власного питання й звітували про ту половину, яку спитали.
Донаповнень системи, кожне з причиною
0→29
Кожен рядок журналу несе колонку «чому інвентар етапу 07 цього не побачив», і причина там цінніша за компонент. Найчастіша: wireframes/_wf.css не має правил для цілої родини (info-*, art-*, chub-*, ov-*, nl-*) - сім екранів групи f4 стилізують себе у власних <style>-блоках, тож інвентар, виведений зі спільного стилю, був сліпий на всю групу одразу.
Партії, різані за флоу, і що кожна доводила

Не за алфавітом і не порівну. Екрани одного флоу ділять патерни, стани й канонічні дані; розкидані по різних партіях, вони розходяться в дрібницях, яких поодинці не видно. Канонічні дані названі РАЗ на весь етап - один набір цін, одне ім'я, один датасет, одна дата - і передані кожному агенту дослівно.

#ПартіяЕкранів / сторінокАгентівПитаньЩо доводила
1Стани на пофарбованих базах5 / 15534гейт КОНТРАКТУ. Навмисно зібрана з екранів, чия база вже в кольорі: нового компонента там не чекають, тож усе, що впало, - це контракт, а не система. П'ять правок у формулюванні до другої партії
2Каталог і пошук (f3)4 / 124 + 327три агенти з чотирьох здали НУЛЬ файлів у першому раунді й повний список замовлень замість них. Це контракт, що працює як написаний: бракує - зупинка, а не малювання
3Шаблон інфо-сторінки (f4a)6 / 6320шість тем, одне тіло: чи витримує один компонент шість різних предметів без шести редакцій
4Решта контенту (f4b)7 / 8323сім одинаків. П'ять із класів цієї партії - повтор класу, який уже відкрила попередня, і повтор і є знахідка
5Системні та глобальні (f5)4 / 8319сторінки без шапки. Тут же знайшлись три оголошені списки, спитані лише в один бік
6Квіз (ПОТІМ)1 / 1––не робилась: окремий раунд за словом власника. На карті покриття стоїть рядком із причиною
Контракт етапу як чек-лист

Claude із браузером і Codex по джерелу читають те, що існує, тому пропущений гейт не бачить жоден: кроку, який не відбувся, немає в жодному файлі. Цей прохід питає не артефакт, а процес. Таблиця стоїть окремо від таблиці дефектів навмисно: чек-лист, у якому ніколи не буває «не зроблено», проходять формально.

Рядок контрактуСтанЧим доведено або чому ні
Гейт входу перед кроком 1: усі названі файли перевірені на наявністьзробленоперелік пройдено до першого кроку, брак названо вголос
Три борги закриті ДО фанауту: «контрол без форми», «ПОТРІБЕН СТАН», backlog.md рядок за рядкомзробленоусі три списки порожні на момент першого запуску. Це умова початку, а не побажання: невирішений рядок був би вигаданий заново кожним агентом окремо
Кошторис показаний числами до фанауту, вузли без сірого оригіналу перелічені окремозробленоrollout-table.mjs виводить його з двох реєстрів; без сірого оригіналу - 0, вузлів без вайрфрейма - 1 (0.2 Футер, рендер-функція, а не сторінка)
Контракт лежить у ФАЙЛІ й передається дослівнозробленорозділ D rollout.md, п'ять підстановок на кожен запуск. Вісімнадцять агентів, один текст
Партії різані за флоу; канонічні дані названі раззробленорозділи B і C; шість партій, жодна не алфавітна
Гейт після КОЖНОЇ партії, не лише після першоїзробленоп'ять гейтів, кожен із прийманням у браузері й переклички числом
У файлах екранів нуль @media, transition, animation, @keyframes, <style>, style=, hex, px, назв шрифтузробленоscreen-css.mjs, 140 екранів: усі дев'ять по нулю. Виняток один, оголошений і порахований: 26 відсотків на смугах
Нуль класів поза системоюзроблено на кроці 7, і до нього прилад цього не питавдесятий знак дописаний, знайшов 24 імені на 101 місці, закрив усі. Це найдорожчий рядок цієї таблиці: п'ять партій вважали його виконаним
Кожен новий компонент заведений батьком за п'ятіркою, @import у свою групу рівнязробленоCodex, класи 4 і 5: 93 компоненти, у всіх п'ять місць на місці, 0 імен-привидів, 0 імпортів поза групою
Журнал донаповнень має колонку «чому інвентар 07 цього не побачив» на КОЖНОМУ рядкузроблено29 рядків, колонка заповнена в кожного
Кожен екран прийнятий як НОВА робота: усі стани, заміряні 360, обидві темизробленоaccept.mjs на 341 сторінці при 390 і при 360 (clientWidth === 360 заміряний, не намічений), theme.mjs на 279 із 283
Піксельна звірка «до/після»неможлива за побудовоюу цих екранів немає «до»: у кольорі вони не існували ніколи. Пак каже це прямо, і рядок лишається тут, щоб чек-лист не виглядав зеленішим, ніж він є
Дві переклички числом на кожному раундізробленоекрани (N = M + K) і компоненти (що вперше стало в продукт) - у розділі E на кожну партію
Третій замір перепису знятий по ВСЬОМУ продукту, у двох в'юпортахзробленоcensus.md, розділ «третій замір». Перші два були по вибірці; цей уперше бачить продукт цілком
«Контрол без форми» порожній; мертві класи вирішенізробленоdead-sel.mjs: 3385 селекторів, 94 файли, мертвих 0
Карта покриття перевірена ОБХОДОМ приладомзробленоcoverage.mjs: записів 141, відкрилось 140, зі своїми станами 49 з 49, панель рівно одна на 140 зі 140
Зелене стоїть на тому, що увійшло в ОБСЯГ; свідомо не зроблене - окремим станом із причиною і порахованезробленоквіз, один рядок, не посилання, причина в тій самій клітинці. Прилад падає, якщо виняток перестане когось покривати
Кожна сторінка design/ несе ОДНУ панель; index.html = головназроблено140 зі 140 в обході. index.html - вузол 0.0, хаб зветься overview.html
Жодного лінка на wireframes/ у тілі екраназроблено, з двома оголошеними виняткамишість входжень: 5 на quiz.html (екран без кольорового двійника) і 1 навмисне перехресне посилання з кольорового хаба на сірий прототип, підписане стрілкою назовні. Обидва підтверджені Codex незалежно
wireframes/ не змінено жодним символомзробленоgit status wireframes/: 0 змін за весь етап. Дефекти, знайдені в сірому, названі вголос і полагоджені в кольоровій копії
Список питань субагентів зібраний і зведений класами для етапу 13зробленорозділ F, 123 питання, дев'ять класів, у кожного більше одного входження
Критика в два прилади з верифікацією ПЕРЕД правкоюзробленоCodex read-only по джерелу, Claude у браузері по вигляду. Таблиця нижче несе «хто знайшов» і «знято при верифікації» з причиною
Критика класами: хто знайшов і чим це закінчилось

Два прилади, набори взяті незалежно. Codex читав джерело read-only і питання йому ставились falsifiable: css у файлі екрана, клас поза системою, значення повз токен, порядок @import, п'ятірка компонента, реєстр в обидва боки, лінк у сіре, типографіка, контракт голови. Три агенти Claude відкривали браузер: 360 заміряний, обидві теми, усі стани, по 14, 20 і 46 екранів. Кожен рядок несе, хто знайшов, і знято при верифікації з причиною - інакше знахідка повертається наступного разу тими самими словами.

КласЗнайденоХто знайшовВиправленоЗнято при верифікації
ЗНАК КОНТРАКТУ, ЯКОГО ПРИЛАД НЕ ПИТАВ1 знак → 24 імені на 101 місціCodex (читав контракт і прилад поруч)десятий знак дописано в screen-css.mjs; 23 інертні імені знято правилом, 1 отримало правило в системі–
ПРАВИЛО, ЯКЕ ПРИЇХАЛО БЕЗ КЛАСУ1 з 24той самий прилад.cmp .yes на coach-landing: три клітинки Pro перестали бути жирними, і таблиця перестала сперечатися–
КОЛІР, ЯКИЙ ЛАМАЄТЬСЯ ЛИШЕ НИЖЧЕ 8601 правило, 11 екранівClaude, потік тренерачіп рейки кабінету малював іконку й лічильник роллю СТОРІНКИ на дії, що не інвертується: 2.97:1 у темній. Переїхало на --text-onaction-ink / --line-onaction–
ПРИЛАД, ЩО МІРЯВ ОДНУ ШИРИНУ1той самий агентtheme.mjs ходив лише на 1280, тож «0 зламала тема» було твердженням про одну ширину. Тепер дві, і ширина стоїть у кожній знахідці–
PNG БЕЗ АЛЬФА-КАНАЛУ2 файли, 3 екраниClaude, каталог і системні (знайшов 1); прилад знайшов другийобидва прокеєні. Трансформ існував з етапу 08, перевірки не було - додано key-alpha.py --check–
ЛИПКИЙ РЯД ПІД НЕПРОЗОРОЮ ШАПКОЮ1 правило, 2 читачіClaude, контентна родинашапка тепер публікує свою згорнуту висоту (--shell-header-h), як стендова панель завжди публікувала свою. Літерал 57 лишився запасним–
ПІДЛОГА ФОТОКАРТКИ ПІД ПРОЗОЮ1 сітка, 3 екранитой самий агент.info-grid:has(> .info-card) бере --grid-col-min-panel, який система вже описує саме так. 21 знак у рядку → повна ширина; жоден файл екрана не змінився–
РОЗДІЛЬНИК, ЯКИЙ КАЖЕ «ВИМКНЕНО»1 правило, 15 входженьClaude, потік тренеракрапка мета-рядка носила --mark-disabled (#CCC, 1.61:1) - роль контрола, що ВИМКНЕНИЙ. Відповідь уже була взята в article.css цього ж етапу: --text-muted–
СТАН, ЯКИЙ НІКОЛИ НЕ ПРАВДА1Claude, контентна родинаперша пігулка якірного ряду на content-legal несла .on без скрол-спая; сусідній content-faq не має його взагалі. Дефект є і в сірому - названо вголос, полагоджено в кольорі–
ТЕКСТ, СКЛЕЄНИЙ З БЛОКОМ2 входженнятой самий агент«Stack МагазинДякуємо» на content-reviews; три сусідні екрани з тим самим компонентом і є доказ правильної форми–
РЕЧЕННЯ КОНТРАКТУ, ЯКЕ НЕПРАВДА1, читали 18 агентівClaude, контентна родина«uivChrome() міняє кожну емодзі на іконку набору» - зміряно: uivIcons() на .wf-page не викликається ніколи. Речення виправлено–
ВАГА ШРИФТУ, ЯКОЇ НІХТО НЕ РЕНДЕРИТЬ1 сторінкадетектор impeccable → перевірено вручнухаб просив Inter …;800, а --fw-black це 700 з рішення 7.65 і накреслення 800 у гарнітури немає. 140 екранів були байт-у-байт однакові; вибивався один–
ПОРОЖНІЙ ВИНЯТОК У РЕЄСТРІ ШЛЯХІВ2холостий контроль paths.mjsdesign/system.html і design/content-loyalty.html були оголошені «зниклими», і цей етап їх побудував. Виняток для файла, який повернувся, - найневидиміша дірка, яку може мати перевірка–
ПРИЛАД, ЩО ПИШЕ У ВЛАСНИЙ ПРЕДМЕТ1 файл у коренівласний git statusагент критики лишив content-guarantee - PNG без розширення - у корені репозиторію. crop.mjs тепер відмовляє, а не попереджає–
ЛІТЕРАЛ ТРИВАЛОСТІ В КОМПОНЕНТІ2Codex–знято. visibility 0s var(--dur-slow): у скороченому записі перше число це тривалість, друге - затримка. Рядок закритий на 11.6 тим самим приладом, причина лежить у файлі
ЛІТЕРАЛЬНИЙ КОЛІР У КОМПОНЕНТІ2Codex–знято. У масці колір це не чорнило, а альфа-канал: #000 означає «непрозоро». Роль на цьому місці маскувала б за світлістю чорнила й міняла б сховане при зміні теми. Причина тепер у файлі
ВИНЯТОК ДЛЯ INLINE SVG1Codex–знято. Виняток справді не покриває нічого - і це записано в screen-css.mjs ще на першій партії, разом із рішенням рахувати svg, а не звільняти його
«U+2013 ПОЗА ДІАПАЗОНОМ», 101 ВХОДЖЕННЯ101Codex–знято. Питання було поставлено приладу без правила: – дозволений як діапазон І як позначка порожньої клітинки. Обидві форми typo.mjs вважає своїми, і його вердикт зелений
ЕКРАНИ БЕЗ meta description140Codex–записано як рішення, а не правку. Кожна сторінка design/ це noindex, а SEO-копія належить вузлу IA, і жодного рядка не існує у двох редакціях. Але половина - справжня діра: description є в 6 із 18 ia/docs/pages/*.md, тобто у 12 вузлів його немає ніде. Іде в хендофф
МЕГА-МЕНЮ «ГРЕЙНУТЕ»1Claude, каталог–знято самим агентом. Заморозка кадру в cdp.mjs тримає 12 сусідніх панелей на opacity: 0; обчислений стиль дає 1 на всіх. Прилад було видно у власному вимірі

Нуль там, де його питали. 360 заміряний (clientWidth === 360) на всіх 341 сторінці, 0 падінь · фокус: 2293 контроли, 0 у синьому кільці системи, 0 без кільця · сторінка позаду діалога в tab-порядку: 0 з 26 · tabindex > 0: 0 · мертвих селекторів: 0 з 3386 · мертвих посилань: 0 з 6049 · PNG без альфи: 0 з 29 · класів поза системою: 0.

Що НЕ взято, і чому це не боягузтво. Заголовки одного рангу мають чотири трактування, шість екранів пропускають рівень, вісім порожніх 3:4 плит стоять там, де сусідній компонент малює папір, скелетони недорезервують висоту, поле пошуку на 404 сидить на щаблі 40 при власному правилі системи «44 - тактильний мінімум», мега-меню обрізає останній пункт на висоті 768, «Повторити замовлення» називає дві різні дії на одному екрані, тариф Pro надрукований у п'яти редакціях. Кожне з них - рішення, а розкотка нічого не вирішує: вона множить. Невирішений рядок, доїхавши сюди, був би вигаданий заново кожним агентом окремо - тому він названий числом і відданий власнику, а не залатаний на одному екрані з двадцяти.

/impeccable audit - технічний прохід, п'ять вимірів

Не критика вигляду, а те, що вимірюється. Кожен рядок нижче стоїть на числі з приладу цього репозиторію, а не на враженні; детектор пака дав два класи, і обидва розібрані поіменно в останньому рядку.

#ВимірОцінкаЧим зміряно, і що лишилось відкритим
1Доступність3/4focus.mjs: 2293 контроли, 0 у синьому кільці системи, 0 без кільця · modal-trap.mjs: сторінка позаду діалога в tab-порядку 0 з 26 · tab-walk.mjs: фокус на невидимому 0, tabindex > 0 0 · темна тема після правки 12.10: кожна форма нижче 4.5 провалюється в обох темах, і 26 із них - акцентна кнопка на 3.13, ухвалена власником у DESIGN-artifacts.md. Відкрито: два екрани 5.4a і п'ять станів тренера без доступного <h1> · aria-label не має власника в жодному файлі · шість контентних екранів пропускають рівень заголовка
2Продуктивність3/4transition: all: 0 · анімуються лише transform і opacity; три переходи розкладки, усі оголошені, два з них у стендовому хромі · <img> у екранах: 31 з 31 несуть loading="lazy", width, height і alt. P2, зміряно: 11.3 МБ PNG - три маскоти 1024×1024 рендеряться в 118-126px (у 8.7 раза більше, ніж треба) і три фото товару 2048×2048
3Теми4/4theme.mjs, тепер на двох ширинах: 98 семантичних ролей, у кожної обидві половини · 0 компонентів читають колірний примітив напряму · 0 площин темної теми без відтінку родини · єдиний літеральний hex у системі - альфа-канал маски, і причина лежить у файлі
4Адаптив3/4accept на 341 сторінці при заміряному clientWidth === 360: 0 падінь · width-sweep: 124 сторінки × 129 ширин, 0 вище підлоги на всіх чотирьох твердих класах · split.mjs: чисто, кожна рамка - функція свого правила на 129 ширинах · bp.mjs: дві точки реєстру й чотири контейнерні пороги, усі названі. P2: .chip--letter 36×40 і щабель 40 у .btn--s / .field--s проти власного правила системи «44 - тактильний мінімум»
5Цілісність реалізації4/4screen-css.mjs: усі десять знаків по нулю на 140 екранах · dead-sel: 0 мертвих із 3386 · п'ятірка компонента: 0 прогалин на 93 компонентах (Codex) · детектор пака: 166 overused-font - це Inter, рішення брифу етапу 06, а не дрейф - і 2 layout-transition, обидва в _stand.css, тобто в стендовому хромі, обидва оголошені на етапі 11
Разом17/20Good - слабкі виміри названі, і жоден із них не P0: усе, що лишилось, має обхід і чекає на рішення власника, а не на правку

P0: нуль. Жоден екран не заважає довести роботу до кінця. P1 закриті цим кроком (чорнило на дії в темній темі; кнопка, що перетинала межу власної картки на 360-400). P2 і P3 перелічені вище й у backlog.md.