audit: M3 STOP 1 - the shell, the home page, and the six leaking declarations
gates / gates (push) Successful in 6m30s

Measured on the deployed page: 21 requests / 285 KB, 4 181 px at 1440 and 7 530 px
at 390 - less than half the live home page's height - zero third-party hosts, no
overflow, and no contrast failures after two fixes.

Records three things worth keeping beyond this session:
  * the six declarations that leak from site.css into the shell, because later-wins
    is per PROPERTY not per rule. Only one was visible; the rest were found by
    diffing declaration sets.
  * R-930 arriving a second time by another route: fixing the website's .cta-button
    did not fix the controller's .btn-primary, which the shell imports.
  * a measurement trap: a background tab freezes CSS transitions AND rAF, so the
    drawer read as permanently shut when it was fine. Setting transition:none
    before measuring gives the real end state; an rAF await froze a probe for 45s.
This commit is contained in:
2026-10-11 14:00:32 +02:00
parent 11242c5110
commit 698ec9b561
5 changed files with 103 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
# M3 — the shell, and the home page inside it (STOP 1)
Built 2026-10-11 on `felhom.eu` `7413e0dfab` + 2 (the brief's baseline plus the R-899 close and the
mockup ruling). `felhom-controller` `dcd89364a4`, **read only**.
**Live: <https://felhom.eu/preview/m3/>** — `noindex`, blocked by `robots.txt`, no sitemap entry, no
link from a live page. The live site is untouched.
## Part A — the shell
`website/assets/shell.css`: **117 rules copied verbatim** from the controller's `style.css`, plus
**exactly one adapted rule** that says so (`body.shell { display:flex; min-height:100vh }`, which
lives in the controller's base rather than in a component). The generator names every rule it copies
and **refuses to write the file if one has disappeared upstream**.
That refusal already earned itself twice in this session:
- `.sidebar::-webkit-scrollbar` does not exist upstream (only the `-track` override does);
- `prefers-reduced-motion` is split across **five separate blocks** in the controller, and reading
only the first would have silently dropped four rules.
The bare `body { flex-direction: column }` that broke M1's phone layout is copied this time, by
name, along with `body.nav-open` and the `no-js`/`js` pair.
## The thing that was wrong, and how it was found
`shell.css` loads after `site.css`, but **"later wins" is per property, not per rule.** Where
`site.css` declares something the controller's rule does not, the website's value survives inside
the shell. Diffing the two files' declaration sets per selector found **exactly six** such
declarations:
| Selector | Leaking | Effect |
|---|---|---|
| `.nav-links` | `display: flex`, `gap: 32px` | the sidebar menu rendered as a **horizontal row** spilling across the content column |
| `.lang-globe-menu` | `top`, `right` | fought the controller's `bottom`/`left`, so the globe opened the wrong way |
| `.page-header` | `padding`, `text-align` | the website's centred subpage header fought the controller's left-aligned flex row |
Reset in `site.css` (the website's own file), so `shell.css` stays a verbatim copy. Only the first
was visible on the page; the other four were found by diffing, not by looking.
## Measured on the deployed page
| | current live `/` | `/preview/` | **`/preview/m3/`** |
|---|---:|---:|---:|
| Requests, first load | 13 | 12 | **21** |
| Weight, first load | 308 KB | 270 KB | **285 KB** |
| HTML document | 35 KB | 26 KB | **24 KB** |
| Height, 1440 px | 10 967 px | 6 385 px | **4 181 px** |
| Height, 390 px | 19 913 px | 10 145 px | **7 530 px** |
| Third-party hosts | 0 | 0 | **0** |
| Horizontal overflow at 390 px | none | none | **none** |
The extra requests are `shell.css` and the four app logos in the hero window. The page is still
lighter than today's live home page and **less than half its height**.
**Contrast: no failures.** Everything measured with translucent ancestors composited. Two rules
copied from the controller did fail at first and were fixed:
- `.btn-primary` 4.01:1 (white on `--blue`, 13.6px/600) — **R-930 arriving a second time by another
route.** Fixing `.cta-button` on the website did not fix the *controller's* button, and the shell
imports it. Same remedy the operator chose for R-930: 1.2rem/700 puts it in WCAG's large-text
band, where 3:1 applies and 4.01 clears, without touching `--blue`.
- `.nav-group-label` 3.14:1 — moved to `--text-2`.
The sidebar's own call to action is an **outline** button, not a filled one: blue on transparent
measures 6.12:1, and a 19.2px filled button does not fit a 240 px sidebar without wrapping. Measured
both ways. **The controller has both defects on its own surface** — filed, not fixed (read-only).
**Phone:** top bar and burger appear below 768 px, the drawer opens and closes, the backdrop shows,
`body.nav-open` is set, Escape closes it and returns focus to the burger. Focus-visible and
reduced-motion rules both present.
> **A measurement trap worth recording.** In a background tab, Chrome freezes CSS transitions *and*
> `requestAnimationFrame`. The drawer read as permanently shut — `is-open` applied, the right rule
> matching with the right specificity, and the transform stuck at `translateX(-100%)` — and even an
> inline `transform: none` would not move it. Nothing was wrong with the page. Setting
> `transition: none` before measuring showed the real end state: closed at −280, open at 0. A
> `requestAnimationFrame` await in the same probe froze the whole call for 45 s.
## Four changes from the operator's mockup, each with its reason
1. **The active item follows the page.** The mockups show „Indítópult" active on every page.
2. **„Jelentkezem tesztelőnek" is also a button** at the top of the lower group. It is the one action
we want, and the mockup buries it at the bottom of a list.
3. **The „Alkalmazások" categories are anchors on `/alkalmazasok`** — real URLs, no JS-only state, so
they work with JavaScript off and a crawler can follow them.
4. **GYIK was added.** It is in today's nav, and dropping it silently would take a page out of
navigation. That is not a change a restyle gets to make.
## The home page
Six sections, the controller's page header and cards, left-aligned headers. Content is `/preview/`'s
cleaned text, so no new claim and no em dash. `<title>`, meta description, canonical and hreflang are
**already the final values**, so the switch in Part D needs no head edit. The compact „who is behind
it" row sits by the closing button, as before.
`body` carries `shell page-index`, which reuses the existing `.page-index` content rules (`caps`,
`flow`, `vs`, `band`, `who-mini`) rather than duplicating them.
## Still to do after STOP 1
Every other Hungarian page, then the English twins (Part C), then the whole-site switch on „go"
(Part D). Nothing goes live before that.
Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB