Що лишилось
Крок 6 етапу 08 зводить систему з продуктом і питає три питання: чого система не має, що продукт малює сам замість неї, і що вона носить даремно. Тут відповіді - з числом за кожним рядком і з приладом, який це число повторить: node tools/census.mjs і node tools/scope.mjs.
Крок 1 дав census.md - 22 229 спостережень на 180 екранах - і закінчується власним реченням: «the script is the artifact, not the table». Скрипт не зберегли. Лишився btn-census.json, тобто результат. Отже вимога паку «два заміри одним приладом» була нездійсненною, доки приладу немає, а зібрати його з пам'яті - це рівно та ручна правка, яку репозиторій забороняє для інструментів так само гучно, як для сторінок.
tools/census.mjs зібраний з методу, як його описує census.md: дві ширини (390 і 1280, бо десктопної шапки й мегаменю на 390 не існує), у браузері й ніколи грепом (шапку вставляє _nav.js, у розмітці її немає), обчислений стиль замість написаного правила, і тест на контрол дослівно - a / button / label / [role=button] / [onclick], або елемент, який вводить cursor:pointer, якого немає в батька.
Чого не відтворено, і це сказано, а не підігнано
census.md згортає коробчасті контроли у 24 форми на чотирьох осях і виключає чіпи, таби, мініатюри, пагінацію та поля зі сім'ї дії - за списком класів, який жив у втраченому скрипті й ніде в прозі не записаний. Підганяти числа, доки вони не зійдуться з опублікованою таблицею, довело б лише те, що їх можна підігнати.| статичний обхід | з розгортанням панелей | |
|---|---|---|
| завантажень (екран x ширина) | 460 | 460 |
| відкрито панелей перед читанням | – | 11 946 |
| спостережень клікабельного | 35 714 | 63 154 |
| коробчастих контролів | 7 118 | 14 896 |
43% клікабельної поверхні продукту лежить за станом, і обхід, який читає лише намальоване, не бачить жодного відсотка з них. Це стосується й 22 229 кроку 1: той замір знято статично, і саме тому два заміри не зводяться арифметично.
Системі не бракує нічого. Кожен контрол сірого шару або має компонент, або живе на екрані, якого ніхто не фарбував.
Два кандидати повернулись, і обидва стояли на wireframes/overview.html - хабі, який перелічує екрани, а не є одним з них: flowlink і sm-item. Хаб виключено тією самою межею, що вже проведена через kit/ і concept/; CLAUDE.md проводить її поіменно.
22 контроли - це тираж, а не діра
Кожне входження сидить на одному з 54 ще-сірих екранів:addr-save (4 екрани) · bsearch (3) · uachip · bcard · chub-goal · chub-cat · thumb · ttl · read · cert · moz · cta · rev-google · q-exit · sc-goal · sc-chip · clr · ov-row · ov-cb · ov-prod · ov-chip · ov-all.Вони закриються, коли їхні екрани отримають колір - роадмеп уже ставить це після етапу 09.
Крок 7.95 переніс вісім приватних стилів потоку тренера в design/system/components/ і заскоупив кожен селектор: .coach .qa-row, .coach .cnew - 360 входжень у 18 файлах. Клас скоупа поставили руками на одинадцять екранів того кроку, на <body>.
Більше його не ставив ніхто. clone-to-colour.mjs бере екран із wireframes/, а в сірому шарі класу на body немає взагалі - 142 файли, 142 голі теги. Тож кожен екран стану, пофарбований на 8.13 і 8.14, приїхав без нього, і на цих екранах увесь тренерський шар системи інертний: не перебитий, не програний за вагою селектора, а просто такий, що жодного разу не збігся.
tools/scope.mjs ставить питання браузеру як різницю, а не як список імен: додай клас, прочитай обчислений стиль кожного елемента, забери клас, прочитай знову. Зрушили 23 екрани.
| кольорових екранів без скоупа, який носить їхня база | 23 |
| з них рухають 40 і більше елементів | 9 |
найгучніший - coach-session-priceblock | 87 з 1 434 елементів, 56 селекторів на 87 |
Чий це скоуп - написано в самому екрані, а не вгадано
Кожен стан закінчує свій скрипт викликомwfBar('<база>.html', '<стан>'), а кожна база називає саму себе - отже стан носить рівно те, що носить його база. Альтернатива напрошувалась і була хибною: зв'язка зі wfHeader('coach') / wfCoachNav( ловить 36 екранів і промахується на трьох, які клас уже носять - cart-coach, coach-landing, coach-verify це екрани тренера без тренерської рейки.Ще п'ять екранів зрушать, і фарбувати їх не можна
Саме вони й доводять, що скоуп несе навантаження, а не прикрашає:concept/directions (203 елементи від 2 селекторів), account-orders (67 від 2), kit/order-row, kit/badge, checkout-loggedin. Там .coach .x зіткнеться з x, який означає інше - тобто рівно з тим, задля чого простір імен і заводять. Перевірка показує їх окремим списком і ніколи не пише в них.Чотири екрани носять скоуп і нічого ним не ловлять (17.08.2026, було один):
cart-coach, cart-coach-empty, coach-home-error, coach-home-loading - і це рішення працює, а не дрейфує: приватні правила, які користувались неймспейсом, переїхали у свої компоненти, а правилу всередині coach-cabinet.css вже не треба, щоб екран казав .coach. Список РОСТЕ в міру завершення роботи, тому він у звіті й не валить гейт. Вирішено 2026-08-15: лишаємо, і перевірка перестала звати це дефектом (пункт 6 нижче): правило, яке ним користувалось, переїхало на справжнього сторожа ще на 7.96, а неймспейс, що сьогодні нічого не ловить, коштує один токен класу - тоді як неймспейс, якого бракує на одному екрані, коштує цілого класу тихих багів. Питає перевірка тепер протилежне: екран, що носить скоуп, якого не носить його база.| на кроці 6 | 2026-08-17 | |
|---|---|---|
| екранів із приватним ПРАВИЛОМ | 31 | 2 |
| приватних правил усього | 1 154 | 0 |
| з них перемальовують клас, який система вже має | 886 | 0 |
| з них оголошують те, чого немає більше ніде | 210 | 0 |
Нуль. Останні два були одним відкладеним рішенням, а не двома роботами - .cv-card{ max-width: 560px } на coach-verify-error і coach-verify-deadend, - і 17.08.2026 його взяли, а не відклали вдруге: замір, якого відкладенню бракувало, виявився тим, що його вирішує. Див. пункт 2. Права колонка це перезамір тим самим приладом, а не 1 154 мінус те, що пішло.
«Перебивають» міряли як «такий клас у системи теж є», а на екранах станів тренера це було не одне й те саме - до 2026-08-14 система туди не дотягувалась зовсім, тож приватний блок був не шаром зверху, а єдиною фарбою на сторінці. Числа лишились; слово - ні, і правдивим його робить прохід вище.
Дванадцять найгучніших екранів - усі в потоці тренера, тобто в первинній аудиторії:
| екран | приватних правил, що перебивають систему |
|---|---|
coach-session-addclient | 74 |
coach-session-addempty | 74 |
coach-session-priceblock | 67 |
coach-session-oos | 65 |
coach-session-loading | 64 |
coach-session-newclient | 52 |
coach-home-empty | 44 |
coach-home-free | 39 |
coach-tariff-cancel | 34 |
coach-order-error · coach-order-loading | по 33 |
coach-clients-cap | 30 |
Це не косметичний борг, і один заміряний дефект це довів - але не з тієї причини, яка тут стояла
coach-session.css відповідає телефону через @media (max-width: 479px): .qa-row складається у два рядки, і дія бере весь другий. Базовий екран це правило читає і на 360 проходить. Чотири екрани станів - ні: «Додати клієнту» звисало на 10px за край, а html{ overflow-x: hidden } ці 10px обрізає, а не прокручує, тож правий край кнопки був недосяжний. node tools/accept.mjs 360 давав 4 провали на 204 екранах.Причина, записана тут, була хибна, і хибну лишено навмисне. Тут стояло «приватний блок виграє в підключеного стилю». Не виграє:
.qa-row це один клас, .coach .qa-row це два, тож система вже важила більше. Правило не збігалось узагалі, бо сторінка ніколи не була всередині .coach. На вагу селектора списали те, що зробив відсутній скоуп - і речення звучало досить правдоподібно, щоб браузера ніхто не спитав.Виправлено 2026-08-14 через
tools/scope.mjs --apply: accept.mjs 360 дає 0 на 205 екранах. Приватні копії .qa-row лишились на місці й тепер програють системі в кожному оголошенні - тобто переїхали з «перебивають» у інертний набір нижче.І саме тому етап 10 не може початись поверх цього. У продукті 222 медіа-блоки: 170 у системі і 52 у приватних блоках цих 31 екрана, які додають 7 власних меж поверх системних. Шкала не зводить того, що не лежить у системі.
Мертвих не лишилось. Шість видалив власник 2026-08-14; сьомий був помилкою приладу.
Ще дві купи названі, а не пораховані як дефект: 30 класів за станом, якого обхід не досягає - кожен пише скрипт, отже вони живі; обхід кличе всі open* / toggle*, але не вміє скролити (stuck, pdp-stuck, uiv-scrolled) і не проходить потік далі першого кроку (auth-load, auth-spin). І 43 чекають на свій екран - носить сірий шар, кольорового двійника ще немає; здебільшого system-page.css (16), cookie-banner.css (15) і account-shell.css (10).
Прилад помилився чотири рази, і всі чотири помилки однієї форми
Кожна відповідала на питання поруч із поставленим, і кожна давала правдоподібне число.| повідомив | справжня причина |
|---|---|
962 мертвих класи, серед них coach і wfh | мапа будувалась із рядків контролів, тож «не носить ніхто» означало «не носить нічого клікабельного» |
svg jpg png html - мертві класи компонентів | це хвости url(../../visuals/…jpg) і a[href="index.html"] |
12 класів cat-overlay.css мертві | оверлей ніхто не відкрив - census.md уже знімав цю саму знахідку про .tbuy |
menu-pop мертвий | design/system/menu.js:39 ставить його під час зв'язування, а CSS ховає до відкриття; збирач пропускав display:none |
Два були сміттям, одне безкоштовним, три забрали спроєктований стан. Міркування трьох збережені дослівно в docs/backlog.md, тож повернути будь-яке коштує рядок CSS і вставку.
| клас | рід | чого система більше не вміє сказати |
|---|---|---|
.only-mobile .only-desk | сміття, 6 правил | нічого. Закрило питання, яке account-shell.html тримав відкритим із кроку 5 |
.field--err | дубль імені | нічого. Жодне оголошення не змінилось: рантайм пише .err, і стан спрацьовує як раніше |
.certthumb--pending | стан | «сертифікат заявлений, але файлу ще немає» |
.qans--wait | стан | «магазин готує відповідь» |
.tsx--unproven | стан | різницю між доведеним і недоведеним знаком довіри - а «спершу довіра» це принцип 1 |
262 з 1185 приватних правил верхнього рівня міряються як інертні: 215 не ловлять на своїй сторінці жодного елемента (залишок клону - clone-to-colour.mjs копіює блок повного екрана в його порожній і завантажувальний стани цілком), 47 ловлять і не рухають жодного значення. Сам лише coach-order-loading це 37 із 42.
Розріз наклали, і доказ його спіймав
tools/tree-diff.mjs - git archive еталона в окреме дерево, два сервери, один Chrome, порівняння обчисленого стилю кожного елемента по 40 властивостях на 390 і 1280 - знайшов 9 зрушень на 5 екранах: coach-clients-cap, -empty, -error, -loading і coach-home-loading. На 390 рядок рейки став помаранчевим (rgb(242,240,237) -> rgb(255,90,0)), на 1280 сторінка виросла на 555px. Усе відкочено, повторна звірка дає нуль.Причина - метод, а не баг. Прилад міряв кожне правило поодинці, з усіма сусідами на місці, тобто відповідав на питання «чи зайве це правило за наявності всіх інших». Інертність не додається. На coach-clients-cap приватний блок тримав і .acc-nav, і .acc-link[aria-current="page"]: кожне окремо не міняло нічого, а зникнення обох перетворило рейку на мобільну стрічку чіпів, де поточний чіп account-shell.css фарбує через --bg-action під @media (max-width: 959px).
Два виправлення пішли в прилад і обидва правильні: обхід тепер накопичувальний і проти повного знімка документа (правило перефарбовує лише те, що ловить, але розкладка мандрує - батько росте слідом за дитиною і в селекторі його немає), а набір, знайдений на одній ширині, пропонується назад на іншій, бо їхнього об'єднання не бачив жоден браузер: на 390 прохід може зняти {A,B}, на 1280 {A,C}, і {A,B,C} не перевіряв ніхто.
Розриву вони не закрили. Прилад далі очищає правила, яких свіжа сторінка не очищає. Різниця, найімовірніше, між мутацією завантаженого документа і завантаженням без цих правил - скрипти сторінки вже відпрацювали й відреагували на те, що бачили. Це гіпотеза, а не вимір, і записана вона саме так.
Тож видалення чекає на прилад, якому можна вірити, а доказ лишається воротами. Вимір не змарновано: 262 знайдені, два роди розділені, і tree-diff назве будь-яку сторінку, яку зрушить майбутній розріз - із ширинею, елементом і властивістю.
36 контролів носилиЗакрито 2026-08-14. Уbtnбез рангу й малювались голим текстом.button.cssнемає правила.btn- оздоблення і є ранг - аclone-to-colour.mjsловивclass="btn"іclass="btn dark"цілими рядками, тож кожна кнопка з утилітним класом поруч проходила повз:btn qa-add(14),btn cs-save(7),btn dark cs-go(6),btn dark co-new(3),btn dark cgo-btn(2) і ще чотири, на 13 екранах. Та сама сім'я, що й lookahead 8.13: візерунок, досить тісний, щоб мати рацію про випадок перед собою, і хибний про набір.
Ранг узято з бази кожного екрана, а не обрано руками, і це виявилось суттєвим: сірий шар позначаєcs-go,co-newіcgo-btnякdark- своє слово для головної дії, - а кольорові бази свідомо зробили всі триbtn--outlineна 7.95 і 8.7, бо на екрані одна акцентна заливка, і це не вони. Ранг «заdark» додав би в потік тренера три нові помаранчеві заливки й назвав це виправленням. 34 з 36 відповіла база; двох, на яких продукт відповіді не має, вирішено вtools/btn-rank.mjsіз сусідом, виписаним поруч:cart-coach-empty .contбереbtn--outline btn--sз покупцевогоcart-empty, а.blockedу смузіcoach-session-priceblock-btn--accent btn--lбазової смуги, бо йогоaria-disabled="true"система вже вміє.- Перенести 886 перемальовуючих правил у їхні компоненти. Це було власне тіло роботи, що лишалась, і передумова етапу 10. ЗАКРИТО 17.08.2026: 886 -> 3 -> 2 -> 0.
ОСТАННІ ДВА ПОТРЕБУВАЛИ РІШЕННЯ, А РІШЕННЯ ПОТРЕБУВАЛО ЗАМІРУ, ЯКОГО НІХТО НЕ БРАВ.
.cv-card{ max-width: 560px; margin: 0 auto }стояло наcoach-verify-errorіcoach-verify-deadend, байт у байт однаково, і було відкладене чесними словами «чи стане 560 шириною панелі, вирішує етап 09». Чого відкладення не сказало: третій екран несе.cv-card-coach-verify-loading- і возив іншу відповідь, 828px на 1280, з центрованим заголовком у коробці 778, поки два його сусіди центрували той самий ранг по 510.Селектора, який відділив би два екрани від третього, немає, тож правило не можна було перенести, не вирішивши. Вирішено, і записано поруч із правилом як «змінна -> значення -> чому»:
.coach .cv-cardотримуєmax-width: 560px; margin-inline: auto, бо (1) два з трьох оголошують саме це, однаково, а правило, яке два екрани пишуть однаково, - це правило компонента не в тому файлі; (2) система вже обмежує те, що всередині картки (.cv-lead440,.cv-card.mid .cv-actions340), тож ширина картки - це те, що ці два обмеження вже наполовину кажуть; (3).midозначає «по центру», а 828 завелика, щоб у ній центрувати.A/B у живих сторінках на 1280 / 900 / 390, правило вставлено й прибрано:
errorіdeadendоднакові до байта на кожній ширині й у кожному числі;loading828 -> 560 на 1280 і 900, ряд кнопок переходить у два рядки, картка на 52px вища;loadingна 390 однаковий, бо обмеження там не спрацьовує.scrollWidth - clientWidthнуль скрізь, в обидва боки. Дві з трьох кнопок того ряду - демо-перемикачі прототипу, а не контроли продукту. Скасовується одним оголошенням, і вся ціна помилки - 268px на одному десктопному екрані.Інертну половину знято 2026-08-15: 655 із 1154 приватних правил пішли з усіх 31 екрана, і доказ каже, що не зрушило нічого.
tools/tree-diff.mjs --dirпорівняв обчислений стиль кожного елемента на обох ширинах із деревом, яким воно було за хвилини до розрізу: 62 порівняння, 0 зрушених елементів. Це те саме порівняння, яке відмовило червневій спробі дев'ятьма рухами на п'яти екранах.до після приватних правил на 31 екрані 1 154 499 приватних блоків @media52 19 байтів усередині <style>– 67 723 Старий зонд міряв 262 інертні, цей знайшов 655 - і різниця в методі.
private-css.mjsвидаляв по одному правилу із ЗАВАНТАЖЕНОГО документа, що відповідає на питання «чи зайве це правило ПРИ ВСІХ інших», а інертність не додається.inert.mjsвирішує ЗАВАНТАЖЕННЯМ сторінки без правил, пробує спершу весь блок, а на невдачі ділить його навпіл і пропонує кожен шматок поверх уже доведеного безпечного, тож кожен ухвалений набір перевірений як набір. Далі обидва читання беруться ще раз: обчислений стиль по 85 властивостях разом із::beforeі::after, і хеш PNG.Форма результату - це трансформ клонування, а не випадок. Стани, клоновані з кольорової бази, віддають 88-93% (
coach-order-loading38 з 41,coach-orders-loading28 з 31), боclone-to-colour.mjsкопіює в стан увесь блок базового екрана, разом із правилами для елементів, яких у стані немає. Стани з власною анатомією не віддають майже нічого:coach-verify-tier2 з 27,coach-home-loading1 з 19,coach-home-error0 з 5. 499, що лишились, і є чесним предметом цього пункту.Число, якого ніхто не перезнімав, було 886. Його міряли як «цей клас є і в системі», ще до того, як виправлення скоупа дало системі дістати ці екрани, і відтоді з корпусу пішло 655 правил. Меншим числом воно не переписувалось навмисно: віднімання було б арифметикою, а не заміром.
ПЕРЕЗНЯТО 17.08.2026 ТИМ САМИМ ПРИЛАДОМ І ТИМ САМИМ ПИТАННЯМ: 3, а до кінця дня 2.
private.mjsобходить корпус і розкладає кожне приватне правило за тим, скільки домів мають його класи в системі. Усі категорії порожні, крім однієї: 3 правила, один дім,coach-verify.css- і це набір.cv-card, який пункт 3 відклав на етап 09 рішенням. За цим пунктом немає нічого, чого немає вже за тим; обидві половини списку 2 зійшлись на одному відкритому рішенні.І одне з тих трьох не малювало ніколи, що знайшов той самий прогін: 3 -> 2. З виправленим предметом
inert.mjsобходить 3 сторінки замість 30 і закінчив за 42 секунди, тож спитати було не дорого:coach-verify-loadingвідповів 1 з 1 знімається, увесь блок, пікселі збіглись. Його правило це.cv-card{ padding: 40px 24px }, а система пише.coach .cv-card- (0,2,0) проти (0,1,0), тож екран малює--space-32відтоді, як 8.40 забрав анатомію. Записка над ним казала «40 це щабель, тож відступ екрана очікування це вибір, а не дрейф, і скасовувати вибір це справа етапу 09»; каскад скасував його ще напередодні, і браузера ніхто не спитав. Відкладати це правило означало відкладати ніщо. Це.qa-rowзі списку 2, віддзеркалене: там приватне правило звинуватили в перемозі, якої не було, тут приватне правило зберегли як рішення, коли воно вже програвало. Обидва рази речення було правдоподібне, а замір не взятий.І пункт 2 закрив себе не сам - його закрив прохід пункту 3, тому число й треба було ЗНЯТИ, а не вивести. Поділ на «886 перемальовують» і «210 локальних» був прогнозом двох різних робіт, а робота виявилась одна: правило, скопійоване з компонента, і правило, вигадане на екрані, відповідались одним проходом, екран за екраном, і жодну купу не можна було закінчити без другої. Прогноз був корисний, межа всередині нього - несправжня.
Пункт публікував ще одне число, яке перестало бути правдою: «31 екран із приватним блоком
<style>». 17.08.2026 обидва обходи все ще рахували саме це і показували 30 - при трьох правилах під ними. Двадцять сім із тих тридцяти не оголошували нічого: 22 несли записку на місці, звідки пішли правила, а 5 не несли нічого, крім порожніх рядків, які ті правила займали (cart-coach-empty,coach-client-empty,coach-session-addclient,coach-session-addempty,coach-tariff-cancel). Предмет уprivate.mjsтаinert.mjsпитав «чи є елемент<style>» там, де питання було «чи є правило»; тепер це один предикат уlib.mjs, спільний, а звіт називає сторінки-записки й порожні оболонки окремо, щоб одне більше не ховалось усередині іншого. П'яти оболонкам дано записку, яку носять їхні двадцять дві сестри, з призначенням, вичитаним із системи поіменно.І написання однієї з цих п'яти записок знайшло, де міграція внесла в систему мертвий код
Крок 8.31b підняв#wf-bar{ position: relative; z-index: 80 }із двох екранівcoach-session-add*уdesign/_stand.css, з дев'ятьма рядками про те, чому смуга стенда мусить лишатись над скримомoverlay.cssна 55. Міркування правильне про сірий шар. На кольоровому шарі смуга маєdisplay: noneз 06.08.2026 - її ховає той самий файл чотирма рядками нижче, бо роль хрому тут перебрав.uiv-side; заміряно 17.08.2026:getComputedStyleдаєdisplay: noneі висоту 0 на кожному перевіреному екрані. Ще п'ять правил її фарбували, аbody:has(.cart-drawer) .wf-bar{ position: relative; z-index: 80 }було до того ж дослівним повтором правила над собою. Усі шість пішли;display: none !importantлишається єдиним висловлюванням файла про смугу,!important- бо розмітка пишеid="wf-bar", а id старший за клас.
Міграція, яка перевіряє ПРИЗНАЧЕННЯ і ніколи не питає, чи ПРЕДМЕТ узагалі малюється, перенесе мертвий код у систему й дасть йому дім - і всі гейти пройдуть, бо правило справжнє, значення токенами, а компонент правильний. Список ужитків--text-oninverseуtokens.cssвтратив.wf-barразом із фарбою.tree-diffпоказав «зрушило елементів 39» на кожній сторінці design за це видалення, а екран не зрушив ні на піксель. Він читає обчислений стиль, аquerySelectorAll('*')бачить і схований елемент. Арифметика сходиться точно: піддерево смуги це 13 елементів наcoach-home, 12 наindex, 11 наcoach-tariff-cancel, помножити на три рядки, які прилад читає з елемента - 39, 36 і 33, рівно ті числа, що в звіті, і жодного відмінного рядка поза цим піддеревом. Межу вписано в сам прилад, бо наступний, хто видалить правило зі схованого елемента, прочитає те саме тривожне число. - Вирішити 210 локальних оголошень: компонент кожному або видалення кожному. ЗАКРИТО 16.08.2026, крім трьох правил, свідомо відкладених на етап 09.
tools/private.mjsділить залишок за тим, скільки домів має клас у системі, і перша купа - «один дім, тож кожна різниця це або діра, або воскресіння» - проходиться правило за правилом.на початку зараз приватних правил на кольорових екранах 468 2 з них мають рівно один дім 157 2 екранів, що ще носять правила (з 88) 31 2 приватних блоків @media19 0 компонентів у системі 82 84 Дві з цих клітинок не пережили перезаміру, і це предмет пункту 8
«29 екранів» і «4 медіа-блоки» обидва знімали до останніх блоків купи 1 і більше не перезнімали: порахуємо ще раз 16.08.2026 - екранів було 23 на вході в цей блок, медіа-блоків 1. Жодне з двох не було хибним заміром, і обидва були хибним опублікованим числом - рівно той клас, заради якого зробленоtools/inventory.mjs, і рівно той, до якого він поки не дістає.Кожне закрите досі правило було станом, що заново відкрив рішення своєї бази, і після 109 таких це вже механізм, а не спостереження:
clone-to-colour.mjsчитаєwireframes/, тож клонований стан приїздить із відповідями сірого шару на питання, які кольорова база вже вирішила інакше. Сім екранівcoach-session-*- найчистіший випадок: 31 правило, іcoach-session.cssтаstepper.cssусі чотири з них ВИДАЛИЛИ, з причиною, виписаною поруч із кожним видаленням.Одне з них було живим дефектом на всіх семи
margin-bottom: 76px- це висота липкої смуги, написана як повітря і поставлена на елемент, який на сторінці не останній. Тож нижче 940 воно малювало 76px діру ПОСЕРЕДИНІ екрана, з колонкою підсумку й підвалом під нею, а смуга далі закривала те, що опинялось унизу. Заміряно: проміжок між.cs-panelі.cs-summбув 96px на станах проти 20px на базі; тепер 20px усюди.Найбільший запис купи виявився не правилом, а блоком. 48 приватних правил на чотирьох екранах
coach-clients-*- цеaccount-shell.css, передрукований руками; рішення ухвалене й записане ще на 7.95 і виконане лише частково. Копія дрейфнула на п'яти властивостях (.accпроміжок 20/28 проти 24/32,.acc-prof15/14/13 проти 16/12/12,.acc-tier11px проти 12,.acc-link13/15 проти 8/16, і1frтам, де система пишеminmax(0, 1fr)) і скасувала весь мобільний патерн: приватне.acc-link{ width: 100% }написане без медіа-запиту й перемагає системну стрічку чіпів під 960 за порядком, тож чотири екрани кабінету показували ОДИН рядок на всю ширину там, де решта кабінету показує прокручувану стрічку. Знято; малюєaccount-shell.css.Це та зміна, яку в червні зміряли, назвали регресом і відкотили
«на 390 рядок рейки став помаранчевим» - записано вище, в історії пункту 2. Той помаранчевий і є поточний чіп, що бере--bg-action, тобто власна відповідь системи, якуcoach-homeіaccountпоказували весь час. Відкат був правильний для тодішніх приладів і хибний про екран.Три винятки з механізму, і кожен вартий окремого рядка. Одне правило - помилка системи (
.qadd-res), одне - справжня діра (.cnew .cn-tx), а одне,.cv-card, - система, яка мала рацію про екран, для якого писалась, і хибила про три, до яких дістала. Це найдорожчий рід: вона поклала три екрани станівcoach-verifyу рядок на кожному десктопі, і приватні правила були єдиним, що тримало їх стерпними на 390.Одне правило було мертве так, що жоден прилад у
tools/цього не бачитьmargin-bottom: 4pxпоруч ізmargin-top: 18pxсхлопується, і більший виграє начисто: заміряний проміжок 18px із правилом і 18px без нього, а обчисленийmargin-bottomобидва рази 4px. Усі прилади тут порівнюють обчислений стиль, тож усі називають це живим. Відрізнити змогло лише читання ВІДСТАНІ між двома елементами - це теперtools/gap.mjs.Картка
.cnewвідповіла по-різному на своїх двох екранах, і це аргумент проти суцільного замітання.coach-cabinet.cssзакінчив крок 7.98 запискою наступному: «Whoever confirms the deletion of the block deletes these eight with it» - після того, як прибрав ту саму картку зcoach-homeза те, що вона несла слова й адресу кнопки рейки. Заміряно на 390:coach-home-freeказав «Нова сесія» наcoach-session.htmlза 515px під кнопкою рейки, яка каже «Нова сесія» наcoach-session.html, тож картка пішла, і акцентних заливок на екрані стало 3 замість 4.coach-home-emptyкаже «Зібрати першу сесію» і несе речення, яке 7.98 сам назвав роботою порожнього стану, тож картка лишилась, а шість її структурних правил переїхали в компонент. Відкрите, і воно власникове: цей екран досі наводить дві акцентні заливки на одну адресу різними словами. Принцип 2 каже «один чіткий наступний крок»; яка з двох його несе - це погляд, а не замір.Найбільша окрема знахідка - мапа перейменувань, виконана на базі й не донесена до станів.
coach-tariff.cssвідкривається дев'ятьма пронумерованими пунктами - «TWELVE RULES DELETED, ONE CUT TO A SINGLE DECLARATION, ONE MARKUP OVERRIDE REMOVED, TWO RULES WRITTEN» - і в кожному справжній замір на чотирьох ширинах.coach-tariff.htmlїї несе і має порожній<style>. Два його стани не отримали нічого: інлайн-перевизначення H1, голий.tf-lead,.tf-badgeзамість пігулки стану,.tfov/.tfdlgзамість системного скриму й діалогу, і - пункт 9 -btn--accentна «Скасувати підписку», помаранчева заливка на дії, що припиняє платну підписку, там, деbutton.cssна 7.61 постановив: «the destructive control is the OUTLINE carrying the danger ink». Виконання мапи відтворило її заміри до сотої пікселя на екрані, де їх ніколи не знімали: діалог «before 350 x 357.53, radius 14 -> after 342 x 428.34, radius 12» вийшов 342 x 428.344, радіус 12.<style>наcoach-tariff-cancelтепер порожній.Та сама мапа знайшлась на другому потоці, а з нею - клас контрола, якого прилади не бачать. Три стани
coach-ordersдосі носили голий<h1>і голий.subтам, де 7.96 перевів базу на.acc-h1і.sub acc-sub: заголовок пішов з Inter 22/800 на Oswald 30/600, тобто на лице, яке носить кожен інший екран кабінету. А рядки замовлень наcoach-home-freeнесли<a href="coach-order.html">Деталі</a>узагалі без класу, вбрані приватнимtext-decoration: underlineна 12px, там, де база малюєbtn--outline btn--sіbtn--accent btn--s. Це сім'я пункту 1, іbtn-rank.mjsпроходить повз: він шукає контрол, що «носитьbtnбез рангу», бо саме таку форму робить трансформ, а контрол, який не носить НІЧОГО, у його предмет не потрапляє взагалі. Вихід трансформа отримав прилад, вхід - ні. Записано вtools/README.mdпоруч із самим приладом, а не полагоджено вгадуванням, які посилання є текстовими.ТРЕТІЙ потік знайдено з двома лицями заголовка на один ранг, після кабінету й
coach-orders: базаcoach-verifyмалює заголовок Oswald 30/600 усередині.cv-body, а три його екрани станів малювали свій Inter 22/800 усередині.cv-card. Приєднано, а не видалено:.cv-cardце не.cv-body, тож видалення лишило б трьох ні з чим.А сам прилад роздавав хибні доми
private.mjsчитав КОЖЕН клас у селекторі, тож.loy .lrung.nowреєстрував.nowяк власністьloyalty-rung.css, і приватне.cv-steps2 li.now- чеклист перевірки, який до щабля лояльності не має жодного стосунку, - поверталось як «один дім: loyalty-rung.css», а це читається як вказівка перенести його туди. Тепер усередині одного компаунда назву дає лише ПЕРШИЙ клас. Перекласифікація рухає правила в обидва боки - два файли втрачають хибний запис, чотири отримують справжні, - і саме це каже, що старе прочитання було хибним, а не просто нестрогим. Жоден із дванадцяти попередніх проходів на матчі по модифікатору не стояв; це перевірено, а не припущено.Третє ім'я для картки-скелета, і анатомія, на яку ніхто не відповів.
coach-clients-loadingмалював свої скелети як.skccard- радіус 14, власний тон і радіус.skline, власні ширини 45/68/88 проти системних 50/72/90, - тоді якlisting-loadingіaccount-loadingносять.skcardізskeleton.cssузагалі без приватних правил. Перейменовано в розмітці, п'ять правил пішло. А причина, чому обидва тренерські екрани завантаження виростили однакове приватнеpadding: 15px 16px, у тому, що.skcardкладе падінг на.skb, а в цих двох.skbнемає: у коробки не було нутра. Те саме число на двох екранах - це відповідь компонента, а не екрана:.skcard:not(:has(.skb)){ padding: var(--space-16) }, і два екрани, які мають.skb, зміряли 0 зрушень - це і є весь ризик такої охорони.Порожній стан на одному екрані написаний іменами елементів, а на другому - завеликий.
empty-state.cssмалює свою коробку іменами.ei.et.es.eact, і п'ять кольорових екранів їх пишуть;coach-client-emptyписав.ic/<h3>/<p>, тож увесь його вигляд походив із п'яти приватних правил - включно зі суцільною гранню--line-hairтам, де система малює пунктирну--line-strong, а це різниця між панеллю і заглушкою. Аcoach-home-emptyприватно стиснув повносторінковий.emptybox, щоб той уліз у.acard, - тоді як компонент уже пропонує.emptybox.mini, іaccount-emptyбере його рівно з цієї причини. Обидва полагоджено в розмітці; десять приватних правил пішло, а<style>наcoach-client-emptyтепер порожній.У хвості купи вердикт стає правдою про ІМ'Я і хибою про об'єкт
«Один дім» означає, що клас оголошений рівно в одному компоненті - алеbuy-box.cssоголошує.bb .tier, бейдж гуртової ціни всередині buy-box, тоді як приватне.tierнаcoach-verify-tierце ціла картка тарифу. Три з останніх восьми домів були такої форми (.bb .tier,.acc-prof .avпроти скелетного.sk-prof .av,.goalcta .hintпроти.cs-empty .hint). Теперprivate.mjsдрукує селектор, який породив кожен дім, тож хибний читається як хибний з одного погляду. Та сама правка, яку двома проходами раніше отримавtree-diff: не пом'якшуй вердикт, покажи, на чому він стоїть.Єдине правило, притримане «на погляд», відповіло читанням
.ctab.addнаcoach-session-empty: нотатка казала, що таб має нижню грань, якої база не має, і водночас іншу висоту, 44 проти 90, тож це може бути свідоме «таб, під яким нічого немає».coach-session.cssоголошує обидва -.coach .ctab(три рядки,min-width: 118px,border-bottom: 0, бо таб приєднується до панелі під ним) і.coach .ctab.add(один рядок,min-width: 0, пунктир). Отже 44 проти 90 - це різниця між табом «додати» і табом клієнта, а не між двома редакціями одного таба, а нижня грань була приватним правилом, яке перемальовувало.ctabз нуля, не знаючи, що система її знімає. Погляд побачив би таб, який виглядає нормально; відповіли два правила, прочитані поруч.Перший компонент, народжений із приватних блоків.
.upsellнаcoach-clients-capі.tf-upsellнаcoach-tariff-freeбули однією панеллю під двома іменами, і друга цитувала першу у власному коментарі: «same shape and same reasoning as.upsellon coach-clients-cap.html». Два файли, що погоджуються прозою й розходяться числами, - це визначення компонента, якого ніхто не написав.upsell.cssі є той компонент, із повною п'ятіркою: css,design/kit/upsell.html, рядок у реєстрі стенда, рядок вinventory.md,@importу групу рівня 3. Три значення зведено (падінг 18, тло--bg-surface, заголовок--fs-16), жодне не рухає більш ніж на 2px.Другий компонент, і копія назвала атом на ім'я, перш ніж передрукувати його.
.tierнаcoach-verify-tierі.tf-colна двох екранахcoach-tariff- це картка Free / Pro у двох редакціях: та сама робота, згода в прозі, розбіжність у кожному числі. І обидві власноруч набрали ОБЛИЧЧЯ.acard- грань, радіус, тло, тінь, падінг, - причому власний коментар.tierНАЗВАВ той атом у реченні над копією. Прочитані з живих сторінок на 390, вони збіглися по всіх п'яти властивостях. Це перевиведення з посиланням на джерело: кожне значення правильне, кожен токен правильний, і наступна зміна картки продукту дійде рівно до однієї з двох.plan-card.cssі є той компонент; розмітка носитьacardна всіх трьох екранах; п'ять оголошень зникло.
Один каже «цей ми РАДИМО» - акцентна грань, запрошення. Другий каже «на цьому ви ЗАРАЗ» - чорнильна грань, твердження про акаунт, і акцент там відхилено вголос ще на 8.7. Звести їх в один стан означало б узяти сенс одного екрана й покласти на інший..tier.proі.tf-col.onлишились двома станами навмиснеЧотири дефекти вийшли разом із ним, усі зміряні. Ціна на екрані вибору стояла в Inter там, де ті самі цифри на екрані тарифу йдуть у моно -
.tier-priceприєднано до спискуprice.css, і.tf-price2теж, а це мій власний недогляд кроку 8.28: той прохід узяв ранг і повітря й не пішов за родиною..tier-flagвиявився п'ятою редакцією пілюліbadge.cssі стояв на 3px вище за.tf-miniчерез єдине оголошення, якого копія не написала, -line-height. Галочки списку були набрані в розмітці як<span class="m">✓</span>. А.tier-cta{ display: block }тихо перетворював флекс-бокс.btn--fullназад на блок. Два списки на ОДНОМУ екрані малювали те саме речення двома способами - галочка на body-чорнилі вгорі, крапка на secondary внизу - і тепер малюють одним.tree-diffпояснює всі 33 зрушені елементи на кожному екрані тарифу і 4 перейменовані рядки.А інвентар виявився не інвентарем
Додавання рядкаplan-card.cssпоказало, щоinventory.mdне містить жодного з восьми тренерських компонентів, які зайшли на 7.95 і 8.7; щоupsell.cssлежить там як молекула, тоді як його власна сторінка стенда називала його рівнем 3; і що колонка «Lines» - це знімок кроку 5 (tabbar.cssчитається там як 25, а на диску 72). Усі три записані у сам файл, під таблицею. За другим стоїть правило: тренерська група вindex.css- це група СКОУПА, а не рівня, тож будь-який файл, покладений туди, втрачає єдине місце, де його рівень було видно.КУПА 1 ЗАКРИТА, І РЕШТА ТЕЖ
Лишалось два правила, обидва.cv-card{ max-width: 560px; margin: 0 auto }- наcoach-verify-errorіcoach-verify-deadend, свідомо відкладені на етап 09. Узяті 17.08.2026, щойно зміряли третій екран, який несе той самий клас. Третє правило стояло поруч до того ж дня -.cv-card{ padding: 40px 24px }наcoach-verify-loading- і відкладеним рішенням не було зовсім: воно програє.coach .cv-cardза специфічністю й не малювало ніколи. Див. пункт 2 про обидва.Останні чотири правила купи 1 виявились чотирма різними файлами, і жодне не було збігом імен. У кожного був справжній дім, на який перепис указував не з того боку.
.sk-profнаcoach-home-loading- це не «.avз account-shell», це 15 правил, що передрукували екран завантаження покупця, який не має жодного. І скелет, який вони малювали, був обіцянкою про екран, якого вже немає.що скелет обіцяв екран малює рейка 5 рядків стовпчиком, 358 × 216 стрічка чіпів 48 заввишки під 960 смуга 358 × 48 358 × 145.17 ( .cstat)CTA 358 × 86 нічого - .cnewвидалено на 7.98сітка 2 коробки поруч, 316 3 картки на всю ширину, 1265.34 І
.skpulseне стояв на жодному елементі сторінки, тоді як кожен скелет на боці покупця дихає..sk-spinу власному коментарі казав «this was the third edition» і не поставив наступного питання;skeleton.cssна нього відповідає: «one slow breath, NEVER A SPINNER». Екран-скелет, який ще й крутить, говорить двома мовами завантаження одразу.А тоді фотографія знайшла те, повз що пройшли всі числа
Переписаний екран збігся з двійником за кожним заміром, і картинка була порожня: біла картка профілю і сім порожніх пігулок. У двійника - теж, іaccount-loading.htmlвіддавав це на 390 весь час. Причина - одне речення: ці смуги є ВІДСОТКАМИ, а під 960 їхні контейнери розмірюються по них..acc-prof .who- флекс-дитина без нічого, що її розтягує (0.00 × 34, тримає смугу 90%-від-0);.acc-linkпід 960 - це чіп, а чіп розмірюється по вмісту (сім чіпів по 34.00 з нульовою смугою всередині). Два оголошення на тримачах, інлайнові ширини - геть з обох розміток (інлайн б'є будь-яке правило компонента), і:has(.skline), щоб три задеплоєні екрани акаунта показали 0 зрушень, а не «ну візуально нічого не змінилось»..ac-cli- це п'яте ім'я рядкового рунґаradio.css: вибрати клієнта зі списку і є вибором опції з кількох. Рядок отримав ховер, натиск, кільце фокусу і родинне тло вибраного - жодного з чотирьох він не мав..tf-incl li.offпішов додому поруч із галочкою, якій він протилежність, і заодно владнав знак, який 8.29 узяв неправильно (\2715, а не тире: правило про тире - про тире В ТЕКСТІ)..cs-emptyбув шостою приватною редакцією.emptybox, третьою в цій купі.Купа 2, другий блок: модалка додавання клієнта, 32 правила -> 0
Це діалог-РЕДАКТОР ізclient-dialog.cssпід шістьма іншими іменами, і приватна копія побудувала з нуля не той із двох діалогів того файлу: власна коробка 440 на радіусі 14 проти.cemodal460 на--radius-12, а закриття - голий<a>на 19px без ховера, без кільця фокусу і без цілі дотику, на модалці, для якої це єдиний вихід. Три речі справді нові: список, що прокручується, і пунктирний запуск пішли в компонент, а#wf-bar{ z-index: 80 }- уdesign/_stand.css: смуга, яка каже, ЯКИЙ це екран, має лишатись над скримом на 55, і це потрібно кожному екрану стану, що відкриває модалку.І ті самі 27 пікселів, які діалог тарифу зміряв на 8.7
«Додати першого клієнта» поруч зі «Скасувати» іде 154..387 у в'юпорті 360 - і сторінку це не прокручує: скрим обрізає, тож правий край головної дії просто недосяжний, а всі гейти читають 0. Два діалоги, по одному заміру кожен - правило стало компонентовим, копія з тарифу пішла.Холостий контроль сторінки стенда був червоний, і його ніхто не читав
kit/client-dialog.htmlдрукував «5 названо словами, але не показано в демо» стільки, скільки існує, - звірено з деревом ДО того, як цей прохід її торкнувся. Вердикт малюється в браузері, а жоден гейт туди не дивився. Теперaccept.mjsйого збирає - власними словами тієї коробки, а не другою реалізацією тієї ж перевірки, бо дві реалізації можуть розійтись.А сортування, яке пояснювало ті 19 сторінок, лестило - і його зняли читанням
Перша проба ділила 179 класів на «пише JS» (70) і «винне демо» (109), питаючи «чи трапляється цей рядок у JS-файлі»:classList.addАБОclass="x"всередині скрипта. У цьому репозиторії друга половина не означає нічого -wireframes/_nav.jsі є будівник сірого прототипу, тож більшість розмітки продукту лежить у рядкових літералах JS. Із 26 класів на семи найменших сторінках 23 виявились розміткою в шаблоні, а справжніх було три. Питання тихо перетворилось на «де лежить цей файл».tools/idle.mjsпитає вузько й перевірювано:classList.add|toggle|remove('x')на елементі, який уже існує.перша проба заміряно клас пише скрипт - це стан, а не демо 70 9 клас, за який сторінка винна демо 109 163 Усі дев'ять станів закрито
Кожен переїхав уKIT_STSіз реченням на своїй сторінці про те, хто його пише і чому він не стоїть у спокої.dr-lockіpdp-stuckкладуть на<html>і<body>, тож намалювати їх означало б одягти стенд, а не демо;catov-openлягає на нижню вкладку, якої на тій сторінці немає взагалі;hidden- це відсутність банера;added- слід дії. Лишилось 15 сторінок і 159 класів, і всі до одного - демо, яке сторінка винна.Сама перевірка лежала в 74 ручних копіях, у п'яти редакціях
Три відрізнялись лише переносом рядка. Четверта -plan-cardіupsell- мала вирізаний пункт про стани, тож ці дві сторінки не змогли б доповісти неназваний стан, якби він у них був. П'ята,icon.html, тримала єдине правило, яке решта 73 загубили: міряти ПІСЛЯ проходів, а не при розборі, бо.uiv-trailставитьmarks.jsна DOMContentLoaded. Тепер одинdesign/kit/_idle.js, і він читає ще й усередину рамки демо - це коштувало рівно 4 класи зі 162 (toolbarтри іco-wrap), але сторінка, червона з неправдивої причини, і є предмет цього пункту.А список винятків тримав два класи, які не є станами
Наaddress-cardуKIT_STSстояли.addr-del-rowі.addr-back- обидва тут-таки намальовані на сторінці, а вмикає їх не клас: рядок видалення ховає атрибутhidden, «інший спосіб» -.mode-editна модалці. Найдешевший спосіб позеленити цей гейт - припаркувати клас у винятках, тож виняток тепер має власний холостий контроль: голий ідентифікатор, який css компонента оголошує класом і жоден скрипт не перемикає.Перші п'ять сторінок закрито, і жоден із шести класів не був прикрасою
.fsheet-ovбракувало тому, що збирач ішов деревом панелі, а підкладка їй сусідка..ceovдовелось поставити окремо від.wf-ov: двіfixed-підкладки наinset: 0в одному в'юпорті читаються як один темний прямокутник..oosbtnсвідомо зняли з цієї сторінки на 7.91 за те, що вона малювала його контурним, - тепер він стоїть там, де в продукті, всередині.bb .buyrow..pdpпереїхав у рамку навколо власної смуги, бо смуга вирощує ціну на 960 саме ТОМУ, що.pdpвідвів рейку покупки в другу колонку. А.ptabsвиявився геть іншою смугою вкладок, яка ділить файл, - і це питання етапу 09.І перше ж справжнє демо привело живий дефект на екран покупця
Плашка «★ Популярне» лягає на назву товару -design/listing-list.html, перша картка, перекриття 10 x 14px на 390 і на 360, на 1280 чисто. До 559.pcard-lстає сіткою56px 1fr, фото звужується до 56, а плашка всередині нього -position: absoluteбез обмеження ширини, і її 77px переходять у текстову колонку, що починається на 101;overflowу.lphнемає. Друга плашка, «✦ Новинка», вужча на 13px і не зачіпає назву випадково, а не за правилом. Не полагоджено навмисно: обрізати слово, стиснути в трикрапку або лишити саму зірку - три різні відповіді про те, що екран каже на первинній ширині. Рішення власника.Ще три сторінки, шістнадцять класів, і всі однієї форми
filter-rail,auth-dialog,cat-overlay. Жоден із шістнадцяти не був варіантом того, що вже стояло на сторінці: кожен - обличчя компонента, якого в спокої не існує, з однієї з двох причин. Ширина, яка його не малює:.hrail-display: noneдо 960, а флайаут і підкладка несуть!importantдо 860, тож на ширині рейки фільтрів уся ця сім'я не малює нічого, і жодне правило стенда цього не змінить. Тіло, яке переписується цілком: діалог входу має шість станів, оверлей - три рівні, і обидва замінюють панель повністю, тож.auth-loadіснує лише вloading,.auth-alt- лише вerror,.wf-catov-goal- лише на рівні цілей.Жодна з п'яти нових рамок не набирає розмітки - вона натискає
wfHomeRail({ open: true }),wfAuthGo('loading'),wfAuthGo('error'),catOverlayCat(0),catOverlayGoals()- власні функції продукту, ті самі, які викликають наведення й натискання. Сторінка, що передруковує те, що видає будівник, показує власну копію компонента, а не компонент.А заблокована ця робота була ще 24 копіями одного скрипта
Механізм підгонки рамки - той, що дає<iframe>висоту вмісту й масштабує в'юпорт 1180 у вужчу колонку, - лежав інлайном у 24 сторінках побайтно, і ніс обмеження, яке ніколи не було рішенням:querySelector, однина. Сторінка могла тримати рівно одну рамку; друга завантажилась би й лишилась на типових 150px. Теперdesign/kit/_frame.jsіquerySelectorAll. Це не прибирання мимохідь:filter-railпотребує двох рамок,auth-dialog- трьох, і кільком сторінкам із тих, що ще винні, теж треба більш ніж одна.Ще дві сторінки, двадцять класів, і сторінка під шухлядою
cookie-banner: діалог налаштувань пишеwfCookie()разом зі смугою, і він лишається закритим, доки хтось не натисне «Налаштувати», - тож десять із п'ятнадцяти класів не мали форми спокою взагалі.cart-drawer: три інші обличчя живуть на трьох інших екранах, а сторінка під шухлядою належить цьому ж файлу -.cart-behind,.cart-ov,.ph-grid,.ph-cardсусіди шухляди, і вся суть.cart-behindу тому, що кошик - шухляда поверх сторінки, а не сторінка сама по собі.Третя екстракція за день, і вона не косметична
Бут-блок рамок - список ініціалізаторів, який робить демо поведінкою, а не позою, - лежав у 33 однакових копіях. Теперdesign/kit/demo/_boot.js, і в ньому дві речі, яких у копіях не було. ГачокFRAME_STATEвикликається в одній точці: після ініціалізаторів, щоб будівники існували, і до проходів іконок і знаків, щоб розмітка, яку збудував стан, отримала свої гліфи. Покладений у кінець - як зробила б пряма екстракція - він лишає щойно зібрану панель в емодзі: це той самий дефект, який 7.78 виправив для тоста, а 7.87 для каталожного оверлея. І шлях до ассета, який будівник набирає руками: чотири будівники вdesign/_nav.jsпишуть відносний до документаsrcу створений елемент. На кольоровому екрані це правильно, а рамка лежить двома рівнями глибше, тож той самий рядок дає 404. Знайдено порожнім кошиком, який намалював биту картинку замість ведмедя.А відкрита панель привела знахідку, більшу за обидва компоненти
Контейнер кожної відкритої фіксованої панелі малює типове синє кільце фокусу Chrome -auto 1px rgb(0, 95, 204), синій, якого немає в жодній палітрі системи. Причина не в цих файлах: пастка фокусу з 7.85 ставитьtabindex="-1"на верхню відкриту панель і фокусує контейнер - навмисно, «щоб він оголосив власну назву й не вибирав дію за того, хто ще не прочитав панель». Це правильно. Кільця для цього контейнера ніхто не оголошував: система описує:focus-visibleпокомпонентно, для контролів. Заміряно на трьох справжніх кольорових екранах, не на стенді:#fsheetнаlisting.html,#city-dlgнаindex.html,#wf-catovнаproduct.html- усі три однаково. Не полагоджено: «зняти кільце з контейнера, який не є ціллю» і «дати контейнеру системне--color-focus» - різні відповіді про те, чи має людина з клавіатурою бачити, що фокус переїхав. Рішення власника.Ще три сторінки, 31 клас, і два з них виявились не демо
.mega-pinnedі.pinned- не стани продукту. Єдине, що їх ставить у всьому репозиторії, - чотири сірі екраниwireframes/megamenu*.html, іscreens.mdкаже прямо: «.mega-pinnedтримає відкритим для демо». Клас, чия мета - дати демо потримати панель відкритою, не підробляється тим, що демо тримає панель відкритою. Меню кабінету потребувало двох рамок:.cab-lvl- рядок лояльності покупця,.cab-tier- пігулка тарифу тренера, і одна.cab-headвідповідає обом ролям.system-pageпобачив систему вперше: усі шістнадцять його класів лежать на чотирьох сірих екранах без кольорового двійника, і нові рамки вантажатьsystem/index.css.Два з одинадцяти класів buy-box - мертвий код, і це третій список
.bb .tierі.bb .qtyне носить ніхто. Питання поставлено рендеру, а не розмітці, бо коробку частково будує JS: чотири екрани несуть.bb, і на кожному 0 збігів. У сірому шарі теж нічого: єдиний.tierу репозиторії - наwireframes/coach-verify-tier.html, і це картка тарифу зі скоупа.coach, ніколи не всередині коробки покупки. Кількість продукт рахує трьома іншими іменами, кожне у своєму файлі -.ci-qty,.co-qty,.oc-qty, - і жодне не лежить у.bb. Видалено, з заміром біля кожного видалення;--line-strongпішов разом із ними й того самого кроку пішов із таблиці токенів сторінки - цеroles.mjsзробив свою роботу.
І.tier- той самий рядок, який збив першу пробу сортування на 8.32, боacc-tierіcab-tierтрапляються вwireframes/_nav.js. Два прилади збиті одним іменем поспіль, і обидва рази виправлення те саме: питати рендер, а не текст джерела.Три відкриті питання закрито власником, і кожна відповідь лягла туди, де прилад може її виконати
1. Фото лишається 84 на телефоні.product-card.cssдо 559:56px->84px, а перевизначення.lphвидалено, щоб стояло базове значення. Обрано за таблицею: усі три засоби знімають накладання, але висота картки 225 в усіх чотирьох варіантах - назва однаково лягає у два рядки, - тож звуження до 56 не купувало нічого видимого й платило за це зіткненням. Ціна: 43px ширини назви. Це єдиний варіант, який лишає слово.
2. Кільце знято з контейнера панелі.[tabindex="-1"].open:focus{ outline: none }уbase.css; кожен контрол усередині панелі зберігає власне:focus-visible.
3. Шість фінішів вирішено, і відповіді лежать у самому приладі. Три написано (coach-clients-cap), три благословлено (home-*). ТаблицяFINISH_DECIDEDуbtn-rank.mjs, бо екран, переклонований із сірого, втратив би ручну правку, а таблиця її повторить.І очевидний селектор для кільця був би регресом доступності
Першим під руку йшов голий[tabindex="-1"]:focus, тож радіус ураження зміряли до того, як щось писати - питанням до рендеру на 88 екранах:div.menu-optна 87,label.co-optна 15,div.menu-listна 15,span.ptabна 12,span.voptна 10,span.ord-tabна 2. Це roving tabindex - неактивні члени складеного віджета, на які стрілки фокус переводять і які мусять кільце мати. Прибрати його там означало б зняти справжній сигнал з усіх меню, смуг вкладок і виборів варіанта в продукті. Жоден із них ніколи не носить.open; кожна панель, яку фокусує пастка, носить.Шість заливок на екрані ліміту стали три
Порахуємо на 390: базаcoach-clients- 3 акцентні (смуга «Нова сесія», «Додати клієнта», «Підписатись»);coach-clients-capбуло 6 - та сама смуга, «Оформити Pro» і ТРИ «Нова сесія» на картках. Екран каже «ви вперлись у ліміт», отже його один чіткий наступний крок - «Оформити Pro», а він був одним із шести, чотири з яких кликали в два боки. Стало 3 проти 3, і найгучніше нове на екрані - апгрейд.Останні дві сторінки: 86 класів -> 11, і checkout-form закрито повністю
Найбільший файл системи взяв вісім рамок, бо тримає вісім облич і дві адреси: власну обрізану оболонку чекауту (.co-head/.co-logo/.co-support/.co-foot- ні меню, ні пошуку, ні каталогу: на екрані, де платять, один вихід і жодного шляху вбік), варіанти ввійшлого й без адреси, екран відхиленого платежу з блоком «замовлення збережено», екран обробки, картку профілю.pfcard, яка не ділить із чекаутом жодного рядка, і два діалоги, які профіль відкриває.account-shellпішов 29 -> 11: сама оболонка, її сітка завантаження, рядок покупця в рейці тренера й шапка обраного.Один клас жив не в тому файлі, і сховався саме тому, що в нього немає розмітки
.smeths- стос кнопок соцвходу під «або» - був оголошений уcheckout-form.css, а трапляється в жодній розмітці: ні сірій, ні кольоровій. Єдине, що його пише, -wfAuthPanel(), тобто діалог входу. Переїхав уauth-dialog.css, обидва оголошення побайтно й кожне у своєму блоці.
Він сидів не там саме тому, що розмітки в нього немає: жоден перепис входжень не міг на нього вказати, і ніхто не спитав, доки цю сторінку не змусили показати клас, якого на її п'яти екранах немає. Це холостий контроль знайшов рід дефекту, під який не було приладу.Останні 11 - це взагалі не кабінет, і це рішення власника
.wt-flow.wt-fh.wt-fnote.wt-screen.wt-sname.wt-st.wt-statesз.base.node.planned.soon- це дерево роадмепу: будуєwfTree(), а викликає рівно одна сторінка репозиторію,wireframes/overview.html. Це хаб прототипу, який перелічує екрани, а не є екраном, іCLAUDE.mdвиключає його з корпусу компонентів поіменно.
Три заміри, і всі три згодні: та сторінка вантажить_wf.cssі ніколи систему;_wf.cssоголошує цю сім'ю сам; і жодна сторінка, яка вантажить систему, цієї розмітки не містить. Тобто копія вaccount-shell.cssнедосяжна - і власна нотатка сторінки вже рахує ціну: 136 зі 169 оголошень файлу, які не збігаються з жодним елементом продукту.
Прецедент - на цій же сторінці:.only-mobileі.only-deskбули тим самим питанням, і власник закрив його видаленням 2026-08-14. Рекомендація: так само. Одноосібно не зроблено, бо той раз був явно рішенням власника, а цей удванадцятеро більший.ПУНКТ 3b ЗАКРИТО: 74 сторінки стенда, жодної червоної
Власник ухвалив: дванадцять правил.wt-*видалено зaccount-shell.css, з трьома замірами, виписаними поруч. Хаб зміряно ПІСЛЯ, а не припущено:wireframes/overview.htmlтак само малює 6 потоків, 50 екранів і 141 пігулку стану, з тією ж гранню, радіусом і формою пігулки - усе з_wf.css, який оголошує цю сім'ю сам. Чотири токени пішли з файлу разом із правилами і того самого кроку пішли з таблиці токенів сторінки -roles.mjsспіймав кожен.
Борг пройшов 179 класів на 19 сторінках -> 0, аacceptуперше на цьому етапі дає 234 екрани, 0 падінь.Що ця робота насправді знайшла, і чого не міг знайти жоден наявний прилад
Три екстракції приладів, усі однієї форми - механізм, передрукований у кожну сторінку, якій він потрібен:_idle.js(74 копії, п'ять редакцій, в одній вирізано пункт про стани, в іншій - єдине правильне правило часу),_frame.js(24 копії зquerySelector, який мовчки обмежував сторінку однією рамкою),_boot.js(33 копії плюс гачок, чиє розташування несуче, і шлях до ассета, який чотири будівники набирають руками).
Два видалення мертвого коду -.bb .tier/.bb .qtyі сім'я.wt-*. Одне правило не в тому файлі -.smeths, який сховався саме тому, що розмітки в нього немає взагалі. Один живий дефект на екрані покупця - плашка на назві товару. І один на весь шар панелей - синє кільце фокусу Chrome.
Жодне з цього не діставалось приладами, які в репозиторії вже були. Усе це - відповіді на питання, якого ніхто не ставив: чи сторінка справді ПОКАЗУЄ те, що оголошує її файл.Купа 2, перший блок: сесія замовлення, 138 правил -> 48
Сім екранів станів тренерської сесії несли найбільший блок, що лишався, а їхня база не має<style>взагалі: базу перевели, стани - ні. Та сама форма, щоcoach-tariffіcoach-orders, вчетверо більша. Мапа - це три атрибути класу, застосовані трансформом, який читає базу, а не шістьма ручними правками; п'ятнадцять селекторів були чистим воскресінням buy-bar, client-row, price, discount, availability і chip.Що стани малювали натомість, на 390: дія липкої смуги 100.50 × 40 проти 243.30 × 64 - під порогом дотику 44px, на контролі, до якого веде вся сесія; «В наявності» у secondary там, де
availability.cssкаже--text-success, тобто на сигналі довіри первинної аудиторії; закреслена ціна в rgb(170,170,170), сірому, якого немає в палітрі; поле швидкого додавання малювало коробку в коробці; чіпи цілей 33.19 заввишки.І чотири прилади дечого навчились.
private.mjsчитав КОМЕНТАР як селектор -withNotesнарощує спан на його примітку, а тут css пишуть усередині приміток, тож два правила були розкласифіковані хибно, і обидві примітки написали два попередні проходи.btn-rank.mjsніколи не питав, чи ранг збігається з базою, і щоб спитати це надійно, знадобилось три ключі - слот, а не клас і не адреса, - плюс поділ, який тепер правило: розмір, що не збігається, - дефект; фініш, що не збігається, - рішення. Аaccept.mjsотримав колонкуdot=після фотографії з двома крапками на кожному рядку наявності: 31 набраний знак на семи екранах, один з них - екран покупця з подвоєною крапкою на дванадцяти рядках.І один раз прилад упіймав мене раніше, ніж я себе. Перше написання правила
.ac-infoвикинулоdisplay: flex; flex-direction: columnяк «те, що блок і так робить із двома блоковими дітьми» - а діти там<span>, і два інлайнові спани в блоці стають в один рядок: «ІгорЦіль: Витривалість · 2 замовлення» на фотографії 390. У коментарі стояло «measured with and without, 0 moved», і нічого зміряно не було. Оголошення повернуто, а хибне речення замінено на те, що сталось насправді, а не стерто. Далі за купою 1: 111 локальних імен без дому, 88 правил на кілька компонентів, 24 частково нових, 2 без класу. 105 мертвихЗакрито 2026-08-15: знято 105 із 57 екранів, і не зрушило нічого.class="dark"уdesign/*.html.Зміряно до того, як чіпати, і саме замір зробив це безпечним. Усі 105 сиділи на контролах, які вже носять ранг
btn--*- тобто слово було заступлене, а не забуте.wireframes/_wf.css:583оголошує.btn.dark; підdesign/.darkне оголошує ніхто - згадки вtokens.css,button.cssіfilter-sheet.cssце коментарі про те, що колись воно важило, аdesign/kit/_page.cssмає.kp-demo.dark, і це власне полотно стенда, а не цей клас на продуктовому контролі. JS його теж не читає й не пише: коженdarkуdesign/_nav.jsіdesign/system/theme.js- це назва РЕЖИМУ ТЕМИ.Правка у двох місцях, і одне з них - трансформ.
clone-to-colour.mjsчитаєdark, щоб вирішити, чи клонований контрол стартує якbtn--accentчиbtn--outline, і раніше ніс його далі в результат - тожdarkце ВХІД трансформа, і з виходу він тепер прибирається. Замітання того, що вже вийшло, живе вbtn-rank.mjs, який володіє атрибутами класів кнопок уdesign/*.html, і воно йде ПІСЛЯ запису рангів: контрол, що приходить якbtn dark cs-go, ще без рангу, тож замітання перед ранжуванням лишило б мертве слово і потребувало другого прогону.Сторож - те, що робить це замітанням, а не
sed:darkмертвий лише там, де його заступив ранг. Усе інше, що носить це слово, потрапляє в список і лишається недоторканим.Доказ:
tree-diff HEAD, 57 сторінок, 114 порівнянь, 0 зрушених, 630 перейменованих рядків - це 105 контролів x 3 рядки (елемент,::before,::after) x 2 ширини, точно.acceptна 360 і 390 по 57 екранах: 0 падінь.А доказ довелось спершу навчити відрізняти перейменування від руху. Кожен рядок знімка починається з
TAG.className, тож зміна класу робила рядок відмінним, поки всі 85 властивостей стояли на місці: перший прогін відповів «114 порівнянь, 114 зрушило» з порожнім переліком властивостей під кожним, і читач, який повірив би заголовку, відкотив би правильну зміну. Тепер зрушило рахує лише властивості, а перейменування називаються поруч окремим числом: рух властивості це візуальний регрес, перейменований рядок - це та правка розмітки, яку ти й робив.Вирішено і зроблено 2026-08-15, власник віддав вигляд. Це таки був баг, і вирішив його замір..cline.oosгасить цілий рядок доopacity: .5.Число в цьому записі було хибне, і справжнє гірше саме там, де це важить. Скомпоноване з поверхнею, а не помножене начисто,
rgb(28,28,28)приopacity: .5на білому дає 3.30:1, а не 1.47 - заміряно в браузері наcart-oos,coach-session-oos,listingіlisting-listпри 390, усі чотири однаково. 3.30 проходить нетекстовий поріг 3:1 і провалює 4.5:1, який стосується того, чим це насправді є. 1.97 у плейсхолдера було правильне і не має значення: коробка-заглушка це декорація.фотографія декорація, порогу немає opacity: .5лишаєтьсяназва і ціна чорнило, 4.5:1 3.30 -> 6.84:1 через --text-secondaryЗмінна - як гаситься недоступний товар
Значення: фотографія лишаєopacity: .5; назва і ціна беруть--text-secondary. Чому: прозорість міняє контраст, не оголошуючи ролі, а назва товару - це рівно те, що тренер читає, щоб обрати заміну, тобто останнє, чому можна бліднути.--text-secondaryце наявна роль приглушеного чорнила, 265 вживань, 6.84:1 на білому.Застосовано в усіх чотирьох місцях, які поділяють це значення, бо одне значення не може мати двох трактувань:
.ci.oos,.pcard.dim,.pcard-l.dimі.cline.oos, яке при цьому переїхало з приватного блокуcoach-session-oos.htmlуcoach-session.css, куди й належить - одне правило з купи пункту 2 заразом.Стан ніколи не тримався на затіненні.
.ci-oostagі.pavail.outкажуть «Немає в наявності» словами, і саме це називає стан; затінення - це наголос.А замір ПІСЛЯ зміни спіймав помилку, яку міркування пропустило.
colorна.prow2УСПАДКОВУЄТЬСЯ, а успадкування програє будь-якому власному оголошенню, хай найслабшому - у.pnewвоно є, тож карточка сітки повернулась із 17.04:1, тобто не приглушена зовсім, точна протилежність правці. Роль мусила лягти на саму ціну. Той самий замір показав, що старе затінення гасило й.cartbtn.notify, «Повідомити про надходження» - єдину дію, яка на цій картці ще можлива. Тепер вона на повну силу, і це правильно: товару немає, а сповіщення є.Доказ:
tree-diff --dir, 88 сторінок, 176 порівнянь, зрушило 10 - це 5 зачеплених екранів на двох ширинах і більше нічого, і кожен рух це абоopacity 0.5 -> 1, абоrgb(28,28,28) -> rgb(91,91,84).acceptна 360 і 390 по цих п'ятьох: 0.Закрито 2026-08-15: лишаємо, і перевірка була неправа, називаючи це дефектом.cart-coachносить.coachдарма.На тому екрані нічого не зламано, і відповідь уже була написана в коді. Єдине правило, яке колись користувалось скоупом, це
.coach .ci:last-child; воно переїхало в.cd-group .ci:last-childна кроці 7.96, і причина записана вcart-drawer.css:.coachне було сторожем, бо його носить кожен кольоровий екран тренера, тож правило діставало все, що носить.ciбудь-де в потоці. Справжній сторож це.cd-group- 2 входження наcart-coach.htmlі 0 наcart.htmlтаcart-oos.html.Лишаємо, і міркування тут навмисно несиметричне.
cart-coachЄ екраном тренера - замкнене продуктове рішення 1, кошик із позначкою клієнта. Скоуп пишеться з бази правилом, а не руками. Зняти його означало б лишити єдиний екран тренера без неймспейса, і наступний скоупований селектор тихо його промине - той самий дефект на 23 екрани, за який цей етап уже заплатив. Неймспейс, який сьогодні нічого не ловить, коштує один токен класу; неймспейс, якого бракує на одному екрані, коштує цілого класу тихих багів.scope.mjsчерез це валив гейт, а тепер питає правильне. Неймспейс, що нічого не ловить, потрапляє у звіт і не валить. Валить те, чого ніхто не питав: екран, що носить скоуп, якого не носить його база - екран, що заявляє потік, до якого не належить. Зараз таких 0.Два застарілі записи:Закрито 2026-08-15, і запис був застарілий сам про себе. Обидва вже виправлені у своїх файлах:design/overview.htmlкаже 50 кольорових екранів, а примітка кроку 8.19 каже 41 ще-сірий.design/overview.html:283несе «87 екранів + хаб (46 покупця, 41 тренера), перераховано 2026-08-14 кроком 6» і називає 50 числом, що застигло на етапі 07, аdocs/decisions.mdпомічає 41 як застаріле поруч із 54 кроку 6. Рядок етапу 07 у README був правильний увесь час.Замість них знайшовся третій, і він не стояв у жодному списку.
design/kit/docs/architecture.mdі його сторінка казали «кольоровий шар це 40 екранів; сірий прототип - 142. У 42 екранів тренера кольору немає зовсім» - і на цій підставі ставили власникові питання про обсяг. Обидва числа зробила неправдою робота цього ж етапу. Запис помічено, а не переписано: це питання, на яке власник відповів 11 серпня, і відповідь без нього не читається.І що тут варто сказати вголос: список застарілих записів сам застаріває. Два пункти полагодили в місці правки, а список про це не почув; запис, якого ніхто не вписав, простояв зі своїми числами чотири дні. Захист, що масштабується, один - питати ВИХІД, а не вести список.
- Жоден прилад не питає, чи опубліковане число ще правда. Кожна цифра на стенді була правильна, коли її писали, і ніхто її не перепитує. Три спіймано руками за два дні (50, 41, 40/42), і щоразу тим, хто відкрив сторінку заради іншого. Форма перевірки відома з тих, що вже працюють: узяти твердження зі сторінки, узяти число з корпусу і впасти на розбіжності -
grey-vars.mjsіvars.mjsроблять рівно це для значень.ПЕРШИЙ ПРИЛАД ЗРОБЛЕНО 16.08.2026:
tools/inventory.mjs, і його предмет це реєстр компонентного шару,inventory.md. Перший прогін: 84 файли проти 73 рядків, 2 рядки на неіснуючий файл, 66 хибнихLines, 58 хибнихScreens, підсумковий абзац каже «70 компонентів: 22/27/21» проти 73 (22/28/23) у своїх же таблицях. КолонкаScreensправильною бути й не могла: то було сканування розмітки, а третину хрому цього продукту пишеwireframes/_nav.jsна завантаженні, тож вона читалаfooter.css1 там, де підвал на 77 екранах.ДРУГИЙ ПРЕДМЕТ ПІДКЛЮЧЕНО 17.08.2026, І ЦЕ ТОЙ, ЩО ЙОГО СПРАВДІ ЧИТАЄ ЛЮДИНА. Реєстр це одна копія твердження «який завбільшки цей компонент»; смужка
kp-metaна кожнійdesign/kit/<компонент>.htmlце ДРУГА, а дрейфує саме друга. Питання H у тому самому приладі, по 75 сторінках стенда, що називають файл компонента:тегів хибних рівень75 0 N рядків73 53 N селекторів51 40 N оголошень46 19 N екранів56 37 числових тегів усього 270 143 Нуль у рядку «рівень» і робить решту читабельною. Перевірка, що знаходить хибним усе, підозріла так само, як та, що не знаходить нічого; одна сім'я, яка повернулась цілком чистою, каже, що парсер і корпус згодні, а дрейф справжній.
Словник вичитано зі сторінок, а не обрано.
loyalty-rung.htmlпублікує «49 селекторів · 61 правило», а її файл міряє 67 селекторів і рівно 61 правило - тобто стенд уже розрізняє два слова, і перевірка це розрізнення береже: селектор це один член заголовка правила через кому на будь-якій глибині, правило це один блок.pdp-tabs.htmlзакріпила інші два: 85 рядків і 102 оголошення, обидва точні сьогодні, проти застарілого числа селекторів. У двадцяти сторінок був правильний підрахунок рядків і у двадцяти семи - оголошень, і саме так конвенції підтверджені, а не вигадані.Закінчення їде разом із числом, бо ці теги це рендер-текст.
button.htmlвіддавала «461 рядків», де 561 хоче «рядок»;breadcrumb.html- «22 екранів», де число хоче «екрани».--applyпише те закінчення, якого вимагає нове число: 1 -> рядок, 2-4 -> рядки, 5+ -> рядків, а 11-14 беруть останню форму всупереч останній цифрі.І перший
Зіставлення тега трималось лише за початок рядка, тож воно читало голову СКЛАДЕНОГО твердження - «3 екрани + значок на 14», «14 екранів, діалог на 5», «291 оголошення без елемента» - як число, яке впізнає, і перезапис міняв увесь тег на два слова. Два з трьох були навіть не про ту саму величину: 291 у cookie-banner це оголошення, які не збігаються з жодним елементом. Відкочено, і зіставлення тепер вимагає, щоб тег був ТОЧНО число + іменник; усе довше це твердження саме по собі й іде в «не дістає». Та сама сім'я, що й строкова заміна в--applyзіпсував тринадцять тегів, ще до будь-якого комітуbtn-rank.mjsна 8.31, і спіймана так само - поглядом на те, що прилад написав.44 числові теги названо недосяжними, а не пропущено мовчки: 13 складених тверджень і 31 корпусне число, якому потрібен браузер і інше питання («106 екземплярів», «470 лічильників», «5 291 входження»). Ті тринадцять і далі несуть те, що несли: їм потрібна людина, яка знає, що означає кожне речення, а не регулярка.
І прочерк, прочитаний як нуль, уже встиг знищити два опубліковані числа
Перевірка завалилаproduct-thumb.htmlза хвилину після того, як сторінку написали: «1 екран» проти клітинки реєстру, де стоїть «–». Реєстр мав рацію.inventory.mjsчитав ту клітинку якsc ? Number(sc[0]) : 0, і то було свідомо - коментар поруч казав «відсутнє читається як 0, а не як невідоме», і це була правда, доки в кожному рядку стояло число. Зламав йогоproduct-thumb.css: він не оголошує жодного власного класу, тож обхід за якорями не може порахувати його екрани взагалі. Межу приладу сплющили у факт про продукт - і--applyтой нуль уже застосував:counter.htmlпоїхав із «19 екранів» у «0»,icon.htmlіз «39» у «0». Обидва повернуто, обидва тепер у «не дістає», і це чесний стан: підтвердити 19 чи 39 сьогодні в цьому репозиторії нічим. Прилад, який не вміє сказати «не знаю», каже число.ПИТАННЯ I, 17.08.2026: рівень записано в ЧОТИРЬОХ місцях, а перевірялись два. Файл оголошує
(level N);inventory.mdкладе його рядок в одну з трьох таблиць;index.cssімпортує його в одну з трьох груп;design/kit/_nav.jsставить його сторінку під один із трьох заголовків. C і D звіряли перші два. Драбина це вся архітектура цього етапу - атом, імпортований після молекул, може бути ними перебитий, тобто рівно та інверсія, задля якої порядок і існує, - а на останні два ніхто ніколи не дивився.файл файл каже index.cssреєстр стенда product-thumb.css1 2 1 menu.css2 3 1 upsell.css2 3 3 Розбіжність із написаною поруч причиною це не дефект:
upsell.cssнесе чотири рядки про те, чому імпортується там, де імпортується, аproduct-thumb.cssне ніс нічого - тож перевірка питає про коментар і розділяє ці два роди у звіті.product-thumb.cssпереїхав у групу атомів, іtree-diffпо п'ятьох екранах на обох ширинах знайшов усі відмінні рядки всередині схованого піддерева.wf-barі жодного поза ним.Два рішення власника, і це різні питання
menu.css: три розміщення і три відповіді - файл каже молекула, імпорт каже організм, реєстр стенда каже атом. Одне з трьох правильне, і в джерелі немає нічого, що сказало б яке.upsell.css: два НЕЗАЛЕЖНІ розміщення згодні між собою і незгодні з файлом - і імпорт, і реєстр звуть панель Pro організмом, і лише її власний вступний коментар каже молекула. Коли два розміщення сходяться проти декларації, помилка радше в декларації - але рівень це архітектурне твердження, тож рухається озвученим рішенням.
16 селекторів у шарі компонентів не збіглися з жодним елементом. Знайдено 17.08.2026 приладом
tools/dead-sel.mjs, зібраним саме під це питання, бо його тут не ставив ніхто:inert.mjsпитає, чи перебите ОГОЛОШЕННЯ, і селектора без елемента не бачить структурно - там немає програшного оголошення, яке можна знайти. Два вже ловили руками в одному файлі, і другий лише тому, що перед ним був перший:coach-order.cssутратив.od-backна 8.7 рахуванням примірників і зберіг.od-line:last-childчотирма рядками нижче аж до 8.52.2925 селекторів у 84 файлах (2215 різних), спитано в браузера на 263 сторінках, що підключають
system/index.css: 16 мертвих, 365 умовних із живим господарем, 6 народжуються в акті (тост, оголошений разом із рядком, який його будує), 4 цей рушій не приймає (::-moz-range-*).Сім із шістнадцяти це одна форма - список через кому, дописаний заради симетрії, де елемент має лише один член.
файл живе мертве поруч button.css.btn--outline .uiv-brand·.btn--s.btn--accent·.btn--ghost·.btn--lfield.css.field-grp > .btn--accent> .btn--outline·> .btn--ghostempty-state.css.emptybox .et:first-child·.es:last-child.empty .et:first-child·.es:last-childОстанній найгостріший, бо файл уже записав це правило чотирма рядками вище: «
.errbox .etніде не буває:first-child, і селектор, доданий під нього, не збігся б ні з чим. Виняток, що нічого не вкриває, валить перевірку так само гучно, як незадекларований випадок; правило теж». А тоді написав два.Решта дев'ять не одна сім'я і не одне рішення:
селектор файл що це .pcard.dim .pold·.pcutproduct-card.cssпритемнені картки є, закреслені ціни є, жодна картка не є обома .pdp-tabs .tprice:not(:has(.told)) .tnewpdp-tabs.cssціна без старої ціни - у демо-товара вона завжди є .skcard:not(:has(.skb))skeleton.cssкартка скелета без блоку кнопки .pl-hw .pl-ic:emptyspec-table.cssслот значка, у якому нічого немає .wfh-meta .wfh-loc .uiv-ic:last-child svgheader.cssгосподаря теж немає .btn--stack .tl .uiv-ic svgstack-action.cssгосподаря теж немає .resend afield.cssблок будує скрипт, і посилання в ньому немає .coach .upsell p bupsell.cssабзац панелі Pro втратив жирне слово «Мертвий» тут означає «не збігся на цих 263 сторінках», а не «не може збігтися ніколи» - і лікуються ці два роди по-різному: правило без можливого господаря видаляється, а комбінація, якої корпус не показує, це питання про демо-дані. Прилад повідомляє факт і відмовляється вгадувати; прочитання за людиною.
ЗАКРИТО 17.08.2026: шістнадцять прочитано, дванадцять видалено, чотири лишено з причиною.
Кожне з дванадцяти видалень несе прочитання поруч із правилом, і кожне з них це речення про ПРОДУКТ, а не про селектор: бренд-мітка називає стороннього провайдера, а провайдер ніколи не є єдиною дією регіону і ніколи не привид (dead-sel0button.css, три); контрол, приварений до краю поля, це той, що поле надсилає, тобто акцент за рангом (field.css, два);.wfh-locтримає одну мітку, а каретка належить лише мовному меню (header.css);.tlце підпис таббару, вписаний у складений контрол так, ніби два підписи взаємозамінні (stack-action.css); кожен.emptyносить гліф над заголовком і дію під тілом, тобто рівно те, що абзац чотирма рядками вище вже вивів (empty-state.css, два); жирне слово панелі справжнє в одній із двох її форм абзацу (upsell.css).Два видалення варті окремого рядка.
.resend aбув чотирма оголошеннями для посилання, якого немає:.resendтримає відлік у<span>, бо доки йде відлік, тиснути нема на що, а живе посилання це<a class="pf-resend">в.otp-note, яке вже малюєcheckout-form.css:50. Мертве правило було дев'ятим двійником того самого контрола, на один токен інакшим, на розмітці, якої ніколи не існувало - тож дивлячись на екран, знайти його було неможливо..skcard:not(:has(.skb))був правильним того дня, коли його написали (8.24, для двох названих тренерських екранів), і корпус з-під нього поїхав: сьогодні дванадцять.skcardі жодного без.skb, а на тих двох екранах слово вціліло тільки в коментарі. Це і є аргумент за обхід усього корпусу, а не того, що крок зачепив.Чотири лишені оголошені в
tools/dead-sel.mjsякKEPT_ON_PURPOSE, кожен зі своєю причиною, і контроль там валиться в обидва боки: запис, який ожив, означає, що випадок настав і нотатку час прибрати; запис, що називає селектор, якого не оголошує жоден файл, означає, що виняток пережив своє правило. Три це стани КРАМНИЦІ, яких немає в демо-каталозі - товар за повною ціною (pdp-tabs.css), товар, якого немає в наявності і який водночас зі знижкою (product-card.css, два). Четвертий - дзеркало тоста:.pl-hw .pl-ic:emptyвбивається актом, бо розмітка везе слот порожнім, аdesign/_nav.js:1461заповнює всі три на кожному завантаженні, тож на момент будь-якого заміру:emptyхибне всюди.2925 селекторів до, 2913 після, і кількість живих не змінилась - 2534. Це і є доказ, що нічого живого не зачепили. Пікселі:
tree-diff --dirпо всіх 88 продуктових екранах на обох ширинах, 176 порівнянь, зрушило 0 елементів.І еталон довелось зібрати, бо
Проти HEAD він каже «зрушило 4», і всі чотири належать попереднім крокам, які досі лежать у дереві незакоміченими - перевішування межі наtree-diff HEADна це питання не відповідаєcoach-order(8.52) і 560 наcoach-verify-loading(пункт 2). Гірше: без названих сторінок він питає git, якіdesign/*.htmlзмінились, і отримує дві, жодної з яких правка стилів не зачіпає взагалі - зміна в шарі компонентів торкається кожної сторінки, що його підключає, і жодного html-файлу. Тож еталон це робоче дерево, у якому лише десять таблиць стилів повернуто з HEAD, і--dirпорівнюється з ним. Порівняння, чиї дві сторони різняться більше, ніж тим, що міряють, це не доказ.
Купа 2, третій блок: скелетон, 20 правил на 5 екранах -> 0
skeleton.css відкривається переписом - смуга «written SIX times in FOUR files», - знятим на 7.28 по 40 кольорових екранах. Тренерський потік увійшов у колір на 7.95, тож перепис його не бачив. Перерахунок по п'ятьох тренерських екранах завантаження дає дев'ять редакцій смуги, і жодне оголошення не замінило видалених правил.| смуга | висота | радіус | ґрунт | де |
|---|---|---|---|---|
.sk-line | 13px | 6px | --bg-sunken | coach-client-loading |
.skln | 12px | 6px | --bg-rule | coach-order-loading, coach-orders-loading |
.qa-skel .sk | 12px | 6px | --bg-rule | coach-session-loading |
.skline | 10px | 4px | --bg-sunken | система, і 78 смуг із 84 |
--bg-rule - це --warm-200, тобто --line-hair
Три тренерські екрани фарбували скелетонну смугу кольором волосини, поки решта продукту фарбувала --warm-100. Зміряно tree-diff: rgb(233, 231, 226) -> rgb(242, 240, 237) на 21 смузі. А сам файл каже це одним рядком: «the ground of a skeleton bar is --bg-sunken and is stated once».А рядки навколо смуг були тим самим компонентом, передрукованим руками. Не схожість - ті самі оголошення поруч: .sk-row = .oc-item (40 / 1fr, gap 11, волосина), .sk-ph = .oc-ph (40 квадрат, радіус 7), .sk-top = .oc-top, .sk-actions = .oc-actions (gap 9, margin-top 14), .qa-skel = .qa-row (44 / 1fr, gap 11, padding 9/0), .skhd = .ccard-hd, .skav = .ccard-av, .skacts = .ccard-acts, .skclist = .clist, .skgrp = .od-grp.
Тому відповідь не «перенести їх у компонент»
Це правило 7.68, дочитане до кінця: скелетон - це обіцянка про коробку, яка його замінить, і єдина обіцянка, що не може розійтися, - сама коробка. Розмітка тих п'ятьох екранів тепер носить.ocard, .oc-item, .oc-ph, .ccard, .clist, .od-grp, .ord, .qa-row - справжнє, порожнє, зі .skline всередині. .skpulse уже був цієї форми і сам про це каже: «the container is usually a real component».Додалось рівно двоє оголошень, і обидва вже були написані двічі. Заглушка кнопки (.sk-btn 38 × 120 і .skacts i 38 із flex: 1), обидві на 2px нижчі за btn--s, чий min-height = --size-40; і .load-note, речення під скелетоном. Плюс три правила, що читають анатомію так само, як двоє з 8.30: що потрібно .od-grp і .ord, коли вони тримають смуги замість своїх справжніх дітей, і що потрібно смузі у флекс-рядку чи в auto-треку сітки - той самий дефект «відсоток від нічого», що його 8.30 зміряв на рейці кабінету, у другому середовищі існування.
Одне з тих трьох правил було написане з розмітки ОДНОГО екрана
Правило тримача один чернетковий прохід читалось.od-grp:not(:has(.od-grp-h)), .ord:not(:has(.ord-body)). Обидві половини клаузи .ord хибні: coach-cabinet.css дає .coach .ord власний падінг, тож правило відповідало на питання, якого ніхто не ставив, - а .ord-body пише лише account-orders, тож сторож зачепив би й чотири справжні картки замовлень на coach-orders.html. Та сама сім'я, що й матч по цілому рядку class="btn" з пункту 1. Знято з читанням поруч, а видалення доводить tree-diff: шість завантажених екранів, перед якими стоять ці скелетони, зрушили 0 елементів на обох ширинах.Це доводить 8.24 до кінця, а не скасовує його
Той крок знявcoach-clients-loading з третього імені скелетонної картки і поставив на .skcard; те саме читання на крок далі каже, що це взагалі не скелетонна картка, а картка клієнта, що стоїть порожня. .skcard лишається каталогу й кабінету, де коробка-замінник це .pcard, - назвати їх це етап 09, а не рух, який цей крок зміряв.Купа 2, четвертий блок: коробка помилки й коробка порожнечі, 26 правил на 7 екранах -> 0
empty-state.css ще з 7.28 каже, що порожньо і зламалось - різні речі, і каже це реченням на власній сторінці стенда. Жоден екран тренерського потоку цього не прочитав. .errbox носив рівно ОДИН екран у продукті - account-error, - а токен --line-danger-soft мав рівно одне вживання в усій системі: грань тієї єдиної коробки.| коробка | грань | радіус | падінг | гліф |
|---|---|---|---|---|
.err · coach-client-error | 1px solid --line-strong | 14 | 40/22 | 32px на --mark-disabled |
.cerr · coach-home-error | 1.5px dashed --line-strong | 16 | 44/26 | кільце 60px, --text-secondary |
.ord-err · order-error, orders-error | 1px --line-hair | 14 | 44/24 | немає |
.empty · coach-clients-error | не своя коробка взагалі - ілюстрована плашка каталогу «тут поки нічого» | |||
.errbox | 1px --line-danger-soft | --radius-12 | 48/24 | --text-danger, 34 |
Жодна з чотирьох не несла ролі небезпеки
Не інший відтінок червоного - червоного не було зовсім. Плаский сірий, а наcoach-client-error гліф попередження стояв на --mark-disabled, тобто чорнилі для того, що вимкнено. Первинна аудиторія, найгірша хвилина сценарію - і саме там продукт мовчав про те, що сталося.Разом із ними пішло те, що ці екрани домальовували руками: .err-btns .btn{ padding: 13px 24px } - розмір поверх btn--s, те саме видалення, що 8.30 зробив для .cs-empty .btn; .ord-empty, .ord-err в одному селекторі, тобто одна плашка на дві протилежні роботи; і p.lead на двох екранах клієнтів - це .es під іншим імям, з мірою 42ch на одному екрані й 46ch на другому.
А міри в коробки не було, і саме тому обидва екрани її виростили
.emptybox .es обмежена 440, .errbox .es - 420, а в .empty .es межі не було зовсім. Заміряно на 1280: 660px на coach-clients-empty, 726 на listing-error, 818 на coach-client-empty, 982 на product-error - до ста знаків у рядок. Одна декларація, 440 - число, яке сусідня коробка вже несе. tree-diff каже: рухає рівно один елемент на кожному з чотирьох екранів і нічого на 390, де коробка й так вужча за 440.Двом екранам додано гліф, і це рішення про вигляд, а не замір
Усі інші коробки помилки в продукті несуть⚠️, а коробка, якій компонент фарбує --text-danger, - це коробка, що його чекає. Заодно це тримає чесним правило 8.15: .errbox свідомо НЕ додано в селектор :first-child, бо після цього кроку немає жодної коробки помилки без гліфа, а селектор, що не покриває нічого, - той самий шум, що й порожній виняток. Міркування виписане біля самого правила.Купа 2, пятий блок: потік перевірки тренера, 32 правила на 4 екранах -> 0
Кожне імя в тих блоках мало префіксcv- - це власна анатомія coach-verify.css, яку несли чотири екрани станів, тоді як база не несла нічого з неї. Лишились три відкладені правила .cv-card, і це весь залишок потоку.| що коштувала копія | замір |
|---|---|
.lead - це .cv-lead, у якому бракує одного слова | три редакції: 14px / 13.5px / 13.5px, три відступи, дві міри |
у .cv-lead не було міри | coach-verify-tier малював рядок 828px на 1280 - 93 знаки в рядок |
h1.cv-h1 набраний руками | 24/800 Inter проти --fs-30 Oswald - четвертий заголовок на два лиця |
голий .btn{ display: block } на двох екранах | третій випадок форми після .tier-cta (8.29) і .cs-empty .btn (8.30) |
І перше написання четвертого рядка було хибним - саме тому воно тут окремо
Там стояло, що правило перетворюєbtn--full головної дії назад на блок. Браузер сказав ні: cv-cta написаний btn--accent btn--l btn--full без голого btn, тож правило до нього не діставало взагалі. Заміряно на coach-verify-error на 1280 до і після: воно діставало до другорядної дії, і там робило справжню роботу - контурна кнопка була 510 × 40 з margin-top: 11px, а сам атом дає 203 × 40 без відступу: контрол природної ширини, приклеєний до нижньої грані повношириного. Тож відповідь не в тому, щоб лишити голий .btn. Дві дії стосом - це група, у цього файлу вже був для неї клас (.cv-actions, на екрані глухого кута), і екран помилки просто його не носив. Твердження, яке виживає на одному екрані й гине на другому, - це те, для чого потрібен браузер.text-align: center свідомо вийшов із відкладеного набору
Приватними лишились три правила - .cv-card{ max-width: 560px } двічі й { padding: 40px 24px } раз, - бо яка з відповідей картки стане відповіддю панелі, це рішення. Центрування до цього питання не належить: воно ділить чотири екрани за тим, що вони тримають, а не за значенням. Екран очікування й глухий кут центрують одне повідомлення; екран помилки лишає текст зліва, бо несе список. Тож це .cv-card.mid у компоненті, і все, що випливає з центрування - диск, кільце, лід, підрядок, нотатка, обмеження колонки дій на 340, - випливає з нього в одному місці.Купа 2, останній блок: 25 правил на 8 екранах - і купу закрито
Після потоку перевірки лишились ті самі три атоми, передруковані втретє, плюс чотири падінги кнопок.| атом | що написала копія | що каже система |
|---|---|---|
.acard · coach-home-free, -empty | радіус 14, без плити й тіні; .ah gap 10; капслейбл на --text-secondary; лінк 12.5 | --radius-12, --bg-page, --elevation-1, --space-12, --text-muted, --fs-14 |
.co-status · coach-home-free | 11px/800 на --line-strong, і стан .ok відрізано | --fs-12 на --space-4/--space-12, зелений .ok |
.cl-oostag · coach-session-oos | 11px/800 Inter ні на чому | .ci-oostag: моно --fs-10 на --bg-sunken |
.cs-empty · coach-session-newclient | сьома приватна редакція, іменами елементів | .emptybox з .ei .et .es |
Два падінги кнопок система видалила ЗА ІМЕНЕМ, і екрани їх досі несли
coach-clients.css:411: «.cc-cta .btn{ padding: 13px 22px } DELETED - button.css owns the padding» - а coach-client-loading ніс рівно це правило. :332: «.ccard-acts .btn KEPT ONLY ITS flex: 1» - а coach-clients-cap ніс усі три оголошення. Третій, .cli .cgo-btn, оголошував три речі, які система вже оголошує в трьох різних файлах.А одну правку зміряли, визнали регресом і відкотили тим самим кроком
Порожня коробка ставить.ei{ font-size: 0 } і показує SVG, який кладе marks.js. У приватної коробки такого правила не було, тож її 🛒 малював шрифт - а marks.js 🛒 не мапить, мапить UIV_EMOJI в design/_nav.js. Щойно компонент узяв гору, слот іконки зміряв 259 × 0: знак був не блідий, його не було. Той самий шов, що 🗑 на 7.13 і 📦 на 8.1, тож очевидна відповідь - третій рядок.Він коштував два задеплоєні екрани покупця.
.ei - це ще й слот, який design/_nav.js:1566 заповнює маскотом на cart-empty і cart-coach-empty, і '🛒':'cart' замінив маскота контуром візка на обох. Відкочено; коробка бере 📦, знак, який уже носять три її сестри. Третій маршрут, що пише в той самий елемент, - ось чому шов між двома мапами не завжди закривається рядком у другій.Чотири з восьми екранів завантаження не дихали
.skpulse лежить у системі з 7.28 із власною відповіддю на prefers-reduced-motion, а coach-client-loading, coach-order-loading, coach-orders-loading і coach-session-loading просто ніколи його не отримали - coach-session-loading так і написав у власному коментарі, «static, motion deferred». Тепер усі вісім. І один клас був мертвий з іншого боку: .skel на coach-orders-loading не оголошений ніде - ні тут, ні в сірому шарі. Список 3 питає «який клас не носить жодна розмітка»; це дзеркальне питання, і його не ставить жоден прилад.Крок із патерном - це рефакторинг, і його приймання - нуль зрушених пікселів. Кожне значення нижче переїзд зробив видимим; зняти його - окреме рішення у формі «змінна -> значення -> чому», і жодного з них тут не ухвалено. Вкласти зміну значення в переїзд - це рівно те, як рефакторинг перестає бути доказовим.
1. Ряд дій написаний п'ятьма різними відступами для однієї роботи. tools/pattern.mjs: одна композиція, 70 сірих і 58 кольорових екранів, під 53 іменами контейнера. Із шістнадцяти, що несуть правило, відступ це --space-12 десять разів, --space-8 чотири, голий 9px тричі, голий 10px двічі й --space-16 раз. 9px і 10px не на щаблі - драбина 4 / 8 / 12 / 16 - і coach-clients.css уже записав це у власному коментарі: «третє число на чотирьох рядах дій». Після переїзду кожне відхилення - одне оголошення в одному файлі, написане як .x.actions{ gap }, щоб переважити патерн.
| Змінна | Сьогодні | Кандидат | Чому не вирішено тут |
|---|---|---|---|
.coach .cl-acts gap | 9px | --space-8 | 1px на чотирьох тренерських екранах, і чотири ряди мають спершу узгодитись між собою |
.coach .ccard-acts gap | 9px | --space-8 | той самий 1px, на картці клієнта |
.coach .oc-actions gap | 9px | --space-8 | той самий 1px, на картці замовлення |
.coach .cc-cta gap | 10px | --space-12 | 2px, і це власний заклик екрана до дії |
.coach .od-acts gap | 10px | --space-12 | 2px на замовленні тренера |
.coach .ord-acts gap | 10px | --space-12 | 2px у кабінеті тренера |
.addr-acts gap | --space-8 | --space-12 | уже на щаблі; питання в тому, чи дії картки адреси навмисно тісніші |
.aord-actions gap | --space-8 | --space-12 | те саме питання на рядку замовлення |
.cshelf .cs-act gap | --space-8 | --space-12 | те саме питання на полиці довіри |
.ci-links gap | --space-16 | --space-12 | єдиний, що ШИРШИЙ за патерн, і він тримає два текстові посилання, а не дві кнопки |
2. Два ряди дій не переведено, і обидва названо. .ceact і .cedlg .act - власний ряд діалогу клієнта, вісім сірих екранів і два кольорові: його розмітку будує wireframes/_nav.js, спільний скрипт ОБОХ корпусів, а сірий корпус цей етап не редагує. .sys-acts - ряд службової сторінки, нуль кольорових входжень, тож доводити пікселями нема чого. Етап 12 перезбирає обидва набори екранів і візьме патерн тоді.
3. Продуктова колонка сторінки лежить у файлі, який не входить у систему. .wf-canvas і .wf-page стоять на 129 і 122 сірих екранах, а оголошені в design/_stand.css, який починається словами «хром прототипу і стенда, НЕ частина системи». .wf-page{ max-width: 1200px } - це не хром, це контентна колонка продукту, і етапу 10 вона знадобиться. Лишено на місці навмисно: розміщення файлу - записане рішення кроку 7.26, і виносити продуктову розкладку з нього - рішення власника, а не побічний ефект кроку про патерни.
4. У системі немає класу, що означає «це головна дія екрана». І два документи проєкту суперечать одне одному в письмовому вигляді. DESIGN.md, рядок 44: «One orange per view ... A second filled orange button on a screen means the screen has not decided which step is the main one». button.css, рядок 20: .btn--accent це «the one action of a REGION». conventions.md, рядок 130, на боці зони. Продукт слухає зону на кожному екрані списку, тож застарів саме рядок у DESIGN.md - а його новий читач зустрічає першим, бо він стоїть під заголовком «The rules colour obeys». Кольоровий шар не має чим перевірити жодне з двох прочитань. Видимих .btn--accent буває 13 на екрані, бо акцентну кнопку «У кошик» носить кожна картка; власна позначка сірого шару dark доходить до 5. Фініш і є ранг, і від рангу вимагають означати дві різні речі. Чи потрібна системі окрема роль btn--primary, чи правило належить зонам і класом не перевіряється - рішення власника.
5. .acc-main не оголошений жодним файлом компонента. Стоїть на 43 сірих і 31 кольоровому екрані другою половиною оболонки кабінету, поруч із .acc і .acc-nav, які account-shell.css оголошує. Те саме з .stack, .navlink, .ctrl, .frange і .wfh-cabbtn. Мертвими вони не є - tools/dead-sel.mjs ставить протилежне питання й відповідає 0 - це класи, які носить розмітка і яких не називає жоден стиль системи.
6. Власний текст роадмеп-сайдбара - під 4.5:1, в ОБОХ темах, на кожній сторінці, що його несе. tools/theme.mjs, заміряно: a.nav-top «Дослідження» 4.14 темна / 4.33 світла проти rgb(242,241,238), 14 входжень; a.nav-link «Чому саме так» - та сама пара; підпис рядка «дизайн-процес» - та сама; span.nav-badge-soon - 3.79 / 3.79. Колонка «світла» й каже, чия це провина, і вона каже, що тема не винна: дефект старший за темну тему і живе в /_nav.css, у вигляді кореневого реєстру.
Крок 3 етапу 09 його не створив, але розширив його радіус на одну сторінку: віддавши why.html роадмеп-панель - чого пак вимагає від пункту роадмепу - він завів у це читання другу сторінку design/. Предмет обходу це design/, тож звіт називає дві сторінки; панель стоїть на кожному хабі етапу в репозиторії, тож справжній радіус - усі вони.
Не полагоджено тут із причини, яка є правилом, а не вподобанням: /_nav.css - це вигляд реєстру проєкту, він не належить жодному етапу дизайну, а його чорнило це значення. Змінити його - це «змінна -> значення -> чому», сказане вголос власником. Замір - те, що цей крок був винен.
Наступна реальна сторінка продукту, зібрана з готової системи й нічого більше: вузол 2.2, Ціль-колекція, база плюс три стани, чотири файли. Обрано власником із 54 сірих екранів без кольорового двійника, за мірою, яку називає пак: екран накриває 38 із 84 компонентів, більше за будь-якого іншого кандидата, і стоїть у флоу між двома вже пофарбованими (index -> goal -> listing).
На екрані не написано жодного стилю. Чотири файли не несуть ні елемента <style>, ні атрибута style; вони вантажать system/index.css і хром стенда, як кожна інша сторінка продукту. Усе нижче - те, чого система не змогла, записане, а не домальоване руками.
| Чого бракує | Для чого знадобилось | Який рівень системи закриває | Пріоритет |
|---|---|---|---|
.gnote - примітка під гридом, що пояснює порядок карток за замовчуванням, не має ні компонента, ні правила ніде в системі | goal: колекція за ціллю сортується інакше за звичайний лістинг, і екран мусить це сказати | компонент (тиха примітка під блоком) або варіант seo-text | середній - сьогодні це один абзац на одному екрані, але його нестиме кожна колекція за ціллю |
.actions не має inline-варіанта | goal-empty і goal-error: ряд дій порожнього стану це inline-flex по центру, тобто він стискається під відцентрованим блоком. Патерн - flex, тобто розтягується | варіант патерна (.actions--inline) | середній - саме тому .eact не переводили на кроці 1, і це стосується кожного порожнього стану продукту |
.ctrl не оголошений жодною таблицею стилів | усі чотири екрани, і listing до них | компонент або видалення - клас, який ніхто не малює | низький - уже записано пунктом 5 списку 4, тут підтверджено на новому екрані |
І одне, що НЕ є дірою системи, назване, щоб його за неї не прийняли. Комірка «Списком» у перемикачі вигляду на goal - мертвий <span>, бо goal-list.html не існує в продукті взагалі. Це відсутній екран, тобто рішення IA, записане на стенді view-toggle ще з етапу 08 як єдиний справжній дефект цього контрола. Кольорова копія успадковує його без змін; намалювати йому вигляд «недоступно» означало б вигадати стан, від чого крок 7.31 уже відмовився для чипа з тих самих підстав.
Беклог не порожній, і це та відповідь, яку крок був винен. Три діри системи й одна діра IA - з екрана, який людина інакше назвала б готовим.
Ще дві діри, знайдені проходом критики й позитивним контролем, а не на око.
| Чого бракує | Для чого знадобилось | Рівень | Пріоритет |
|---|---|---|---|
pagination.css не малює власних комірок. .pages a не отримує від компонента ні коробки, ні рамки, ні розміру; на listing кожне посилання вдягли руками на етапі 08 як btn--outline btn--icon btn--s. Тому пагінація нового екрана рендериться голим текстом, і карта фінішів цього не полагодить: посилання не носять жодного класу-ідентичності, тобто ключа, з якого читати фініш, не існує | goal - колекція за ціллю посторінкова | компонент (пагінація має малювати .pages a сама, як button.css відмовляється малювати голий .btn) | високий - єдина знахідка тут, що робить контрол невидимим, і вона дістає ще шість кольорових екранів |
Посилання «наступна сторінка» не має доступного імені. <a href="?page=2">›</a> - шеврон і більше нічого | goal, і та сама розмітка стоїть у сірому шарі ще шести кольорових екранів | мікрокопі плюс розмітка, власність сірого шару | середній |
Клавіатурний прохід читали проти контролю, а не окремо, і це змінило звіт. Перше читання goal казало «78 фокусованих елементів без кільця фокуса» і список цілей менших за 44px. Та сама проба на listing, прийнятому двійнику, відповідає 78 і той самий список - тобто обидва належать спільній оболонці й жодного з них тут не заведено. Що контроль справді виділив - одну дельту: три безіменні фокусовані проти двох у двійника, і третій це шеврон пагінації вище. Знахідка, яку обидва екрани поділяють, - це знахідка про корпус; новина лише в різниці.
І одна, що дістає далеко за межі цього екрана - знайдена позитивним контролем критики. clone-to-colour.mjs, рядок 138, завжди дописував btn--s кожному контролу, який ранжував - кнопку 40px, - тоді як зібрані руками екрани пишуть btn--accent btn без розміру і отримують власні 52px із button.css. Тобто головна дія порожнього стану виходила нижчою за поріг дотику 44px на кожному екрані, який трансформ коли-небудь клонував, і ніщо про це не казало: кнопка має ранг, вона видима й натискна, і побачити це можна лише порівнянням із двійником, зібраним руками.
Розкол чистий, і він же доказ: listing-empty, listing-error, cart-empty, product-oos - зібрані руками - несуть 0. account-empty несе 5, coach-home-empty 3, обидва клоновані. По всій теці design/ вигаданий розмір стоїть на 114 контролах на 43 екранах.
Прилад полагоджено (ранг читається з dark сірого шару; розмір сірий шар давати не має права), і чотири екрани цього кроку приведено до вигляду двійника. Решти 43 не чіпав: зняти розмір зі 114 відвантажених контролів - це зміна значення по корпусу, тобто «змінна -> значення -> чому» і рішення власника, а не побічний ефект кроку про патерни. Кожен із них - головна дія, у яку має влучити палець.
tools/theme.mjs по 276 із 280 кольорових сторінок: чорнило проти
власного ґрунту, поріг 4.5:1. 35 форм стоять під ним. 34 з них провалюються і в СВІТЛІЙ темі -
отже вони старші за тему й належать A10, уже записаному рішенню про акцент на блідому: #FF5A00
на блідому ґрунті це 3.13:1, і кожен підпис btn--accent це успадковує.
Рівно одну форму зламала САМЕ тема - і в цьому вся цінність прогону.
| Що | Світла | Темна | Де |
|---|---|---|---|
span.hptag - надзаголовок першої промо-плитки головної, «Акція тижня» | 5.45 | 2.97 | home-buyer · home-cart, 6 входжень |
Плитка малює ґрунт через var(--bg-page) під фотографією
(banner.css:108), а надзаголовок бере --text-action лише на першій плитці
(hero.css:29). У світлій пара працює, бо блідий ґрунт лежить під світлим фото; у темній
ґрунт інвертується, а фото ні - і чорнило втрачає опору, хоча сама роль має обидві половини.
Роль може мати пару й усе одно провалитись: пара - це про токен, а контраст - про ПОВЕРХНЮ,
на яку роль лягла. Це третя вісь, яку записав етап 08, і це її перший справжній улов.
Тут не полагоджено, і це навмисно
Рішення про значення в формі, якої вимагає проєкт - змінна, значення, чому - і воно власника: або надзаголовок перестає читати--text-action на фото-плитці, або фото-плитка отримує власну роль-серпанок. Вибір тут
згорнув би зміну значення в крок про патерни.Прохід дизайн-рецензії посперечався з двома рядками вище, і джерело обидва рази розсудило проти мене. Знята знахідка лишається видимою з причиною, або вона повертається наступного разу тими самими словами.
«pagination.css не малює власних комірок» - ЗНЯТО. Компонент оголошує ряд, стан «недоступно» і заливку поточної комірки, а коробки не малює навмисно: комірка і є кнопкою, складеною на екрані як btn--outline btn--icon btn--s - рівно те, що пише прийнятий двійник listing.html:184. Системі не бракувало нічого; класів бракувало моєму екрану, разом із aria-current та ім'ям шеврона. Заміряно до правки: комірки 9.6 × 25.6px голого тексту проти 40 × 40 на двійнику, і Tab малює дефолтний синій контур Chrome на теплому нейтральному тлі. Полагоджено проходом у clone-to-colour.mjs, бо карта фінішів не дістає посилань без класу-ідентичності.
«.gnote потребує компонента» - ЗНЯТО, і правда протилежна: розмітку треба було прибрати. badge.css фіксує рішення письмово - .gnote це анотація сірого прототипу, «the coloured clone dropped it, correctly, which is why it renders on 0 of 39 coloured screens», - і клас пішов із системи на кроці 8.10. Двійник тримає те саме правило html-коментарем, «kept out of the visible UI». Мій екран був сороковим і єдиним, хто його малював: 16px повним чорнилом, найгучніший блок нижньої половини сторінки, гучніший за SEO під ним. Замовити під нього компонент означало б повернути в систему рівно те, що система свідомо з себе прибрала. Видалення робили руками на 8.10, тож трансформ його не знав; тепер це прохід.
І одну загострено, а не знято. Перемикач вигляду гірший за «мертву комірку Списком»: на goal обидві комірки це <span> - сірий оригінал пише їх так, тоді як wireframes/listing.html пише обидві як <a href>, - тобто весь контрол випав із порядку Tab, продовжуючи рекламувати cursor: pointer. Це дефект замороженого сірого шару, і він потребує власника, а не кольорової латки.
Заміряно на design/coach-clients.html, рамка спліта і дві її колонки:
| В'юпорт | .clsplit | Рейка (фіксовані 17.5rem) | Деталь |
|---|---|---|---|
| 860 | 528 | 280 | 224 |
| 960 | 628 | 280 | 324 |
| 1024 | 692 | 280 | 388 |
| 1280 | 732 | 280 | 428 |
| 1440 і далі | 868 | 280 | 564 |
Від 860 приблизно до 1010 деталь вужча за список, а на самій точці вона 224px - вужча за телефон. Це не поламано: .cdetails несе контейнерний поріг на 22rem, тож рядки «підпис - значення» складаються в одну колонку і панель читається. Але причина та сама, що зробила --grid-col-min-panel 19rem замість 22rem на кроці 4: оболонка кабінету забирає власну колонку навігації 268px, тож .acc-main на в'юпорті 860 - це бокс 528.
@media питає про ЕКРАН, а цій рамці потрібна відповідь про МІСЦЕ. Відповідь драбини - container-type: inline-size на .acc-main і @container на .clsplit: спліт вмикався б тоді, коли для нього є місце, а не тоді, коли широке вікно. Дві причини, чому це не взято всередині кроку 5, і обидві важити власнику:
- Це міняє, КОЛИ спліт з'являється, тобто рішення, назване вголос, а не рефакторинг.
- Кольоровий корпус не може заміряти це чесно: власна рейка роадмепу стенда з'являється на 1076 і роняє
.acc-mainіз 692 назад до 528, тож контейнерний запит блимав би при перегляді копій і був би правильним у продукті.
ЗАКРИТО, і ціна вийшла на один рядок більша за кошторис. Спершу заміряно: нуль position: fixed усередині .acc-main на всіх трьох екранах клієнтів, тож контейнер безпечний. Кошторис помилився в одному місці: голого @container замало, бо місце немонотонне у в'юпорті - він вмикав спліт нижче 860 (там немає колонки навігації, бокс 828) і вимикав між 860 і 960 (оболонка забирає 268, бокс 532). Правило тепер @media (min-width: 860px) з @container (min-width: 41rem) усередині: спершу оболонка, потім місце. Спліт відкривається на в'юпорті 990 з панеллю 354px, і 224 більше немає.
Початковий кошторис, для запису: один container-type на .acc-main, один запит переїжджає в coach-clients.css, і wfClientSplit() перестає читати --bp-shell-wide через matchMedia, а питає ВИХІД - getComputedStyle(pane).display !== 'none', - тобто рівно те, що цей репозиторій питає скрізь. Спершу перевірити, що всередині .acc-main не живе нічого position: fixed: contain: layout перезакріпило б його на себе, і саме тому рама сторінки не могла стати контейнером на раунді 4.
Заміряно по всіх 84 сторінках компонентів: числа (min|max-width: Npx), написані на сторінці, проти чисел, які файл компонента справді тримає після зняття коментарів. 22 сторінки назвали ширину, якої в їхньому власному файлі немає, крок 5 полагодив дві, яких торкався, лишилось 20.
| Сторінка | Каже | У файлі |
|---|---|---|
account-shell | 640, 959, 960 | 620, 859, 860 |
auth-dialog | 719, 720, 899, 900 | 859, 860 |
checkout-form | 479, 480, 559 | 619, 620, 860 |
coach-cabinet | 520, 640, 720 | 619, 620 |
coach-landing | 559, 980 | 619, 620, 860 |
coach-verify | 520, 760 | 620, 860 |
footer | 479, 720 | 619, 860 |
menu | 859 | 619 |
pdp-tabs | 1180 | 860 |
system-page | 720 | 620, 859 |
trust-strip | 479 | 619, 859, 860 |
buy-box · city-dialog | 479 | 619 |
hero | 720 | 860 |
address-card · button · field · loyalty-rung · product-grid · restock-note | різне | у файлі немає жодної |
Не всі 20 - дефекти, і саме тому це список, а не правка. Сторінка стенда має право називати ІСТОРІЮ: «було 720, стало 640» - це запис, і запис може тримати старе число. Не має права ПРАВИЛО, яке його називає: coach-clients тримав (min-width: 640px) -> .clist у дві колонки у таблиці «Межі» як чинну межу, через чотири раунди після того, як це число перестало існувати. Розділити одне від одного можна читанням кожної сторінки, а не регуляркою.
Сьогодні це не перевіряє ніхто, і в дірки є форма. tools/bp.mjs навмисно виключає стенд зі свого предмета - «у стенді, і це не предмет: 17», - бо сторінка стенда законно показує CSS, який не є продуктовим. Тож числа, які стенд пише ПРОЗОЮ, не перевіряє ніхто, а етап 10 зрушив 27 із них. Перевірка дешева (порівняння вище - п'ятнадцять рядків) і належить або п'ятим класом у bp.mjs зі стендом як явним другим предметом, або в inventory.mjs, який уже читає кожну сторінку стенда й кожен файл компонента і вже падає на дрейфі meta.
Заміряно на design/coach-clients.html, розгортка кроком 10px від 320 до 1600: спліт відкривається на 990 (.acc-main 658), закривається на 1080 (532) і відкривається знову на 1210 (662). Падіння на 1080 - це власна рейка роадмепу стенда, що з'являється на 1076 і штовхає сторінку: кольорові копії на ~216px вужчі за продакшн вище цієї ширини.
Це було правдою завжди і не важило досі. Кожна ширина, яку міряв цей етап, міряна з рейкою в сторінці, але з @media рейка зсувала лише числа. З @container вона вирішує, яку РОЗКЛАДКУ дістає сторінка, тобто засіб перегляду дістав голос у композиції продукту. У продукті рейки немає і розгортка дає один перехід на 990.
Три виходи, жоден не безкоштовний:
- Рейка накриває, а не перебудовує. Правильно по суті - це хром для розглядання продукту, а не його частина, - але вона закривала б вміст рівно на тих ширинах, де з'являється.
- Рейку глушать на час заміру, і всі прилади відкривають сторінки без неї. Дешево для приладів, але тоді ніхто ніколи не ДИВИТЬСЯ на те, що прилади міряють.
- Лишити і друкувати. Те, що стоїть сьогодні:
tools/split.mjsдрукує кожен перехід разом із боксом, який його спричинив, тож мерехтіння лежить у виводі кожного прогону, а не в чиїйсь пам'яті.
Пошук у шапці: обрано «зняти підписи з дій». Зроблено КОНТЕЙНЕРНИМ питанням, а не точкою, тож третій брейкпойнт не знадобився: місце кінчається в РЯДУ, а ширина ряду - не ширина вікна (він обмежений 1200 і має падінги), тож медіазапит міряв би не той бокс. container-type: inline-size на .wfh-main, flex: 1 1 18rem на пошуку, і на @container (max-width: 63rem) слова йдуть. Поріг - це сума, яку ряд мусить втримати зі словами: 65 (лого) + 198 (навігація) + 18rem (підлога пошуку) + 408 (дії зі словами) + 4 зазори.
Слова сховані від ОКА, а не від читача. display: none зняв би доступне ім'я з чотирьох контролів, чий єдиний текст це і є - «Увійти» це вся назва тієї кнопки, - і проміняв би тісне поле на чотири безіменні іконки.
Закрито наполовину, і кошторис помилявся про другу половину. Він казав, що пошук дістане ті 408px. Заміряно після: дії віддають 44, а не 408 (408 → 364), бо кнопки лишають іконки, падінги і бейджі. Поле йде 44 → 88 на точці, 84 → 128 на 900, 204 → 238 на 1010, слова повертаються на 1040. Тобто подвоїлось і все ще тісне між 860 і ~960, а решту з'їдають .wfh-nav (198) і чотири коробки дій (364) - жодне з них не пошукове.
Дешевий наступний крок - мікрокопі, а не розкладка. На тому самому контейнерному порозі плейсхолдер міг би скоротитись із «Пошук товарів, брендів...» до «Пошук»: на 88px довгий показує «Пс», короткий читається повністю. Це продуктовий рядок, тож він належить microcopy.md і рішенню, а не правилу компонента.
Бонус-іконка: обрано нову монету. У наборі було 67 марок і жодна не називала ГРОШІ, тож «Бонуси» носили star, поки три дії поруч називали свою роботу. Новий coin - два концентричні кола на власній сітці набору 24×24 при обведенні 1.9: без блиску і без плюса, бо голос забороняє святкувати баланс. Рядка ніде не знадобилось: icons.html малює набір живим із design/system/icons.js і сам про це пише, «другої копії набору немає ніде», тож гліф з'явився на стенді тієї миті, коли почав існувати. Перевірено в браузері.
menu.css несе їх на .menu-src, і тепер header.css несе ті самі п'ять на підписах дій. Це класичний патерн і він правильний в обох місцях, але друга копія - це те, з чого починається третя. Системі потрібна ОДНА утиліта - клас у base.css або плейсхолдер, - і обидва місця мають на неї вказувати. Дрібно, механічно, і належить тому, хто наступним відкриє base.css.
Темна дірка закрита, і діагноз у беклозі був неправильний про механізм. Він казав --bg-page у banner.css:108. Заміряно: це --bg-inverse у hero.css:29. «Inverse» означає «протилежне сторінці», тож уся сім'я перевертається злагоджено - вугілля у світлій, warm-50 у темній, і --text-oninverse перевертається разом. Не перевертається одне: --text-action, помаранчевий бренду. Та сама фарба зустрічала темний грунт, а потім блідий.
Нова semantic-сім'я, чиї дві половини навмисно рівні: --bg-media, --text-onmedia, --text-onmedia-muted, --line-media. Це не відсутня пара - обидві половини написані, і рівність є рішенням. Аргумент: промо-панель це ПОВЕРХНЯ-КАРТИНКА, а дві плитки поруч несуть справжні фотографії, які теми не вчать. Смуга вже була наполовину незалежною від теми, і перша плитка була відступником. Заміряно після: 5.45 в обох темах, грунт однаковий.
20 сторінок стенда: 49 привидів, і 11 із них законні. Читано посторінково, а не регуляркою, бо сам беклог писав, що регулярка не відрізнить запис від правила. Дев'ять сторінок несли застаріле чинне твердження і перезібрані - переважно секція «У файлі N медіа-умов», яка перелічує умови файла як факт; тепер ці списки генеруються з файла, а не набираються. Ще три - таблиці «Межі» тренерських сторінок. Вісім сторінок називають історію, і це законно. Три стилюють власні демо-таблиці власними запитами - це розкладка стенда, а не компонента, і перший замір порахував їх помилково.
І тепер це перевіряється, що й було справжньою знахідкою. inventory.mjs дістав клас H2: він і так читає кожну сторінку стенда і кожен файл компонента. Обидва законні класи оголошені списками і обидва мають холостий контроль - сторінка в списку, яка більше не несе привида, валить прогін так само гучно, як неоголошена. Обидва класи провалу доведено внесенням і відкотом.
Ховер, доданий щоб полагодити відсутній ховер, не малював нічого. Спіймав tools/vars.mjs у тому самому проході, що його вніс. Нове правило брало --bg-hover - ім'я, яким цю роль називає власна проза етапу 08, - і такий токен не оголошено ніде. Невизначена змінна це найтихіший провал, який має CSS: оголошення стає невалідним на обчисленні, тло падає у початкове значення, і ніхто нічого не каже. Полагоджено повторним ужитком: --bg-sunken це те, що бере кожен інший наведений рядок системи. Відкрите питання - проза, а не код: документація етапу 08 називає стан-токен, якого ніколи не існувало, тож наступний читач потягнеться по нього знову.