## 2026-10-11 (M3) — the whole site moves into the controller's shell
The operator's own direction, after three mockups were rejected: the **controller's frame** (left
sidebar, phone top bar, off-canvas drawer) around **the website's own content**. Switched in one
commit — never half old, half new. 20 pages: 12 Hungarian, 8 English.
- **`website/assets/shell.css`** — **117 rules copied VERBATIM** from
`felhom-controller/controller/internal/web/templates/style.css` @ `dcd89364a4`, 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, scoped so a page without the shell is untouched).
The generator **names every rule it copies and refuses to write the file if one has disappeared
upstream** — which already caught two things: a selector that no longer exists, and
`prefers-reduced-motion` being split across **five** separate blocks, four of which a naive copy
would have lost. That is M1's failure, prevented.
- **`shell.css` loads after `site.css` deliberately.** Thirteen selectors exist in both with
different meanings. „Later wins" is **per property, not per rule**, so six declarations still
leaked through and are reset in `site.css`: `.nav-links` `display:flex`+`gap` (the sidebar rendered
as a horizontal row across the page), `.lang-globe-menu` `top`+`right`, `.page-header`
`padding`+`text-align`. Found by diffing declaration sets, not by looking — only one was visible.
- **The footer is kept**, carried verbatim into the bottom of the content column. Stripping the old
chrome had removed it from all 19 pages, taking with it the only route to the **Adatkezelési
tájékoztató and the Feltételek**, the operator's name and `info@felhom.eu`. Caught before the
switch.
- **The English home page is now a true twin** of the Hungarian one (operator's decision): every
string lifted verbatim from the live English page, except twelve faithful translations of sentences
the `/preview/` round introduced. 35.8 KB → 25.4 KB.
- **Em dashes: 326 replaced** with the Hungarian gondolatjel across 17 pages. The FAQ pages' JSON-LD
is swept with the same substitution so it still equals the visible answers (gate 17 green).
**The legal texts are byte-identical** — proven by a word-level diff with no substitution allowed.
- **`site.css`** gains the M3 page rules, the six leak resets, AA fixes for the copied
`.btn-primary` and `.nav-group-label`, and `overflow-wrap` for long checksums and URLs — the last
one repairing a **pre-existing** sideways scroll on `/letoltes` and `/adatkezeles` (609 px and
478 px at a 390 px viewport, measured on the live pages).
- **`website/preview/` deleted entirely** (the A, M1, M2 and M3 studies) with its `robots.txt` line.
`site.css?v=22` / `shell.css?v=22` everywhere.
- **`scripts/site_gates.py`**: gate 3 extended rather than duplicated — a `SHELL` set whose pages must
carry an **identical sidebar and footer**. `is_en()` makes the language gates path-aware.
`norm_block()` also normalises `is-open`/`aria-expanded`. Every change red-proofed, the loosening
one **both ways**: a one-character menu difference convicts, a state-only difference does not.
**What the head-tag diff caught, and why it was worth doing.** Head tags were captured on all 19
pages before the switch and compared after. The home page was about to ship carrying
**`noindex, nofollow`** from the preview, and had lost `meta keywords`, `meta author`, all seven
Open Graph tags, all four Twitter tags and the `LocalBusiness` JSON-LD — because its head was
hand-built while every other page carried its live one over. Nothing on the rendered page would have
shown it. After the fix the **only** head-tag difference anywhere is the dash substitution inside the
two FAQ pages' JSON-LD, verified by applying the same substitution to the „before" copy and getting
an exact match.
**Live read-back, all 20 pages:** 200, sidebar present, footer present, legal link present,
`?v=22` on both stylesheets. Home page: 12 requests, 282 KB, zero third-party hosts, `index, follow`,
canonical and JSON-LD intact, **0 em dashes**, 10 967 px → 4 340 px tall.
## 2026-10-11 (este) — „Ki áll mögötte" a kapcsolati oldalakra költözött
Operator's call after seeing the preview. **This one IS live**, on `/kapcsolat` and `/en/contact`;
the home page itself is still the old design.
- **The full block moved to `/kapcsolat` + `/en/contact`.** On the home page it sat between the
dashboard gallery and „Hogyan működik?", interrupting *what it does* → *how you get it* with a
life story — and its last sentence, „Ha írsz, én válaszolok", is a contact-page sentence that
belongs beside „Válaszidő". Both halves of the twin moved in the same commit; the English uses the
site's established „the box" and promises nothing the Hungarian does not.
- **The home page preview keeps a compact trace** in its closing call to action: a 56×70 portrait,
one line, and a link to the full block. Deliberate, not a leftover — the audit's **R-11** finding
was „nobody is behind it" *on the home page*, so deleting every human trace would have re-opened
it. The preview is now **9 sections, 9 layout families**, 6 385 px at 1440 and 10 145 px at 390
(from 10 922 / 19 913: 42% and 49% shorter).
- A dedicated `/rolam` page was weighed and rejected: five sentences cannot carry a page, and filling
one would have meant inventing biography.
- **The `.who*` rules are no longer page-scoped.** They were `.page-index .who*`; the block now lives
on two pages and will live on the home page's twin later, so it follows `69035f4af5`'s lesson that
a genuinely shared pattern goes site-wide rather than being duplicated per scope. No existing page
used `.who`, so nothing else moved.
- `assets/operator-portrait-small.webp` — 160×200, 8.4 KB, same crop, metadata stripped and verified
by read-back.
- **A layout bug caught by looking at the deployed page**, not at the markup: `.who-mini` was
`inline-flex` inside a `text-align: center` block, so it flowed onto the same line as the CTA
button and pushed the pair off-centre. Now `flex` with `max-width` and `margin: auto`.
- `site.css?v=` → 14 on all 21 files.
## 2026-10-11 — the footer dash site-wide, and the primary button meets WCAG AA
Two operator decisions taken at the redesign review. **The home page itself was NOT switched** — the
operator chose to sit with the preview, so `/` still serves the old design. Only these two things
changed on it, and on every other page.
- **The footer's em dash became the correct spaced en dash, on all 21 page files** (12 Hungarian,
8 English, plus the preview). It could never have been a one-page edit: `site_gates.py` gate 3
requires every page in a language set to carry an **identical** footer. Verified on all 18 live
URLs after deploy: `em=0 en=1` on each.
**Scope, stated:** this clears the footer only. **300 em dashes remain in the bodies of the other
19 pages** (`gyik` 53, `en/faq` 53, `adatkezeles` 33, `szolgaltatasok-nonpublic` 27, `teszteles` 23,
`en/testing` 24, `index` 17, `en/index` 19, …). Enumerated per page in
`documentation/audits/redesign-2026-10-10/NEXT.md`. The preview is the only page at zero.
- **R-930 — `.cta-button` is now 1.2rem/700** (was 1rem/600). White on `--blue` measures **4.01:1**,
under WCAG AA's 4.5:1 floor for body text; at ≥ 18.66 px and ≥ 700 weight WCAG counts the label as
**large text**, where the floor is 3:1 and 4.01 clears it. Chosen by the operator over darkening
`--blue`, which is shared with the hub and controller UIs. Horizontal padding trimmed 32→26 px to
protect the one-line rule for the longest label.
**Measured, not assumed:** every primary button renders on **one line** and **no page overflows**,
checked in the browser on 11 pages at both 390 px and 1440 px. The defect was pre-existing and
site-wide — it measured the same 4.01:1 on the live page before any of this work — so the fix
reaches the primary button on 16 pages, which is the point. `.cta-button-secondary` is untouched at
7.17:1.
- **`site.css?v=` → 12 on all 21 files.** The pages sat at `v=10` and the preview at `v=11`; leaving
them split would have served a returning visitor the old stylesheet and the change would have
looked like it did not deploy.
## 2026-10-10 (este) — a redesigned home page, staged at /preview/
- **Why:** the home page read as AI-made — eleven sections but only eight layout families, every
section header the same centred two-word-plus-blue-tail shape, the hero showing the **logo** where the
product belongs, and a value proposition („Professzionális otthoni szerver telepítés és
üzemeltetés") that says nothing. Measured audit, against the live site:
`documentation/audits/redesign-2026-10-10/AUDIT.md`.
- **`website/preview/index.html`** — the new home page, `noindex` + `Disallow: /preview/`, not in the
sitemap, linked from nowhere. It becomes `index.html` only on the operator's go.
- **New: „Ki áll mögötte"** with the operator's photograph and five sentences in his own words.
Every claim traced in `audits/redesign-2026-10-10/ki-all-mogotte.md`. The photo
(`assets/operator-portrait.webp`) is cropped from an original that **stays outside the repo**, and all
metadata is stripped and **verified by read-back** (0 EXIF tags, 0 GPS entries, and none of the phone's
identifying byte sequences survive). The original carried no GPS tag to begin with; it did carry the
phone model and the timestamp.
- **Ten sections, ten different layout families.** `why-grid` no longer runs three times and
`apps-showcase` no longer twice: the ten capability cards become three labelled clusters, the three
cloud-problem cards and the four own-server cards merge into **one two-column comparison**, and the two
tile walls shrink to a two-item band that keeps the app names and links to the pages that already list
them.
- **The hero** shows a real dashboard screenshot instead of the logo, is sized by its content instead of a
forced `100vh` band, and drops the infinite float animation. Its sentence is now four concrete facts.
- **Numbers off the mono font.** The `1..5` process badges and `01..05` service numbers are gone
(taste-skill §9.F), and the 3-2-1 figures move to the UI font — together these were the **only** 13
characters on the page loading JetBrains Mono, so the page no longer fetches it.
- **Em dashes: 18 → 0** in the page's own copy. The `
`, meta description, Open Graph, Twitter and
JSON-LD keep theirs by operator decision (they are indexed strings; changing them deserves its own
pass). **One remains in the shared footer**, which gate 3 requires to be identical on all 14 pages —
a site-wide edit, carried as a separate decision.
- **CSS: additions only.** Every new rule is a new class under `.page-index`; nothing existing was
modified, so `index.html` and every other page render exactly as before while the preview exists.
`site.css?v=11` on the preview page only.
- **Gate:** `preview/index.html` is registered in `site_gates.py` `NO_TWIN`, with the reason in a comment
— a preview URL **cannot** go in `TWINS`, because gate 3 wants its nav identical to `index.html`'s
(globe pointing at `/` and `/en/`) while the twin check wants the globe pointing at the pair's own URLs.
The English twin is written in the same commit as the switch, as a real twin.
- **CRLF, again.** The page builder wrote LF and the nav/footer gate went red for the preview exactly as
the 2026-10-10 morning entry above describes. Builder now writes **BOM + CRLF** and asserts both.
## 2026-10-10 — a tester recruitment page, and terms 1.1 (the domain)
- **New page pair: `/teszteles` + `/en/testing`** — the website asked for testers without saying what a
tester needs or what Felhom pays for. The page states it: who it is for (a Hungarian household, no IT
knowledge, but patience), **what you need** (a machine that can stay on and home internet — both
**quoted verbatim from the FAQ** rather than invented, plus a domain), **what you get** (the six
promises of the test terms §3, nothing new), what we ask for (feedback; the terms' own „keep your own
copy"), and **how many places there are**. No price, no availability promise, no response-time promise.
- **Operator ruling D1 (2026-10-10) — the domain:** registered in the **tester's own name**, Felhom pays
its fee **for two years**, and **the tester keeps it** when the test ends or they leave. DNS is managed
with a token scoped to **that one zone only**. Recorded in `CONTEXT.md`.
- **Operator ruling D2 (2026-10-10):** the closed test runs with **at most 5 households**; the page says
„legfeljebb 5 háztartás".
- **Terms 1.1** (`feltetelek.html`, record `documentation/legal/feltetelek-1.1.md`): one new section,
**§4 (the domain)**, with the D1 text. Sections 4–11 of 1.0 are renumbered 5–12; nothing else changed.
No document or page referenced those numbers — checked before renumbering. The terms' §11 promises
testers an e-mail before a change, so one is drafted at `marketing/testers/EMAIL-terms-1.1.md` for the
operator to send.
- **Every „Jelentkezem tesztelőnek" button now goes to the page**, not to an anchor or the contact form:
the home page hero (was `#zart-teszt`) and its „Zárt teszt" section (was `/kapcsolat?tema=zart-teszt`),
and the English pair. **The contact form needed no change** — `?tema=zart-teszt` already preselects the
closed-test subject on both contact pages, so the page's apply button uses it.
- **Registered and listed:** the pair is in `site_gates.py` `TWINS` and `URL` (gate 13 refuses a page the
gates do not scan), and both URLs are in `sitemap.xml` with their hreflang trio — 18 URLs now.
- **Encoding, the hard way:** rewriting pages with a Python helper converted five files from the working
tree's **CRLF to LF**, which made `index.html`'s nav and footer differ from every other page's and
turned the nav/footer gate red for all 15 pages at once. The cause looked like a content change and was
not. Restored to CRLF, BOM intact; `site_gates.py` green.
## 2026-10-10 (afternoon) — the phone menu works with JavaScript off; the dashboard pictures retaken
- **R-903: on a phone with JavaScript off the menu links and the language globe were unreachable** (the three-line
button is scripted; the list sat off-canvas). `site.css` now has `@media (max-width: 900px) and (scripting: none)`:
the list sits in the header as a wrapped row and the header scrolls with the page. Script-on pages are unchanged.
`site.css?v=9` on all 18 pages. Measured in headless Chrome at 376 px, JavaScript off, `/` and `/en/`: links reachable
0/7 before, 7/7 after; with JavaScript on, the closed menu is as before
(`documentation/audits/register-shrink-2026-10-10/r903-phone-nojs.txt`).
- **R-910: all eight `dashboard-*.webp` retaken** on demo-hp's household guest (Launcher, Apps, Paperless-ngx's page on
controller 0.305.0; Backup → Apps on 0.307.0), hu + en, 1440 × 900, WebP q82. The Apps card shows the new header
(tags on their own row). Captions unchanged — every caption's claim still holds. Privacy scan:
`documentation/audits/register-shrink-2026-10-10/r910/`.
## 2026-10-10 — two new apps on the apps page: Grocy and LubeLogger
- **Two cards added** to the „Otthon & Életmód" / "Home & Lifestyle" section of both apps pages, in the
same commit: **Grocy** (household stock, shopping list, barcodes, chores) and **LubeLogger** (the family
car's services, fuel, reminders and costs). Both went through `NEW-APP-CHECKLIST.md` end to end;
the records are in the catalog and the evidence in `documentation/audits/new-apps-2026-10-10/`.
- **Assets**: `grocy-logo.svg` is grocy's own `public/img/icon.svg` with its single fill made white, like
the other logos; `lubelogger-logo.png` is the app's own icon with its dark background dropped and the
mark made white, the same rule SparkyFitness's PNG follows. The six screenshots are each app's own
**Hungarian** UI with a household's own data, taken headless on the bench from the published template.
- **The app count moved 56 → 58** in every place the website states it, in both language sets (15 places
each): the apps page title, meta description, og:title, twitter:title, the JSON-LD `numberOfItems`, the
page's own sentence and its stats tile; the home page's meta description, feature heading and line; two
FAQ answers and their JSON-LD copies; and the technology page's bullet. The open-source tile moved
**49 → 51** (both apps are MIT). Checked by re-running the same patterns against the new number.
- **Not changed, and said here instead:** `marketing/facebook/COPY.md` §2 still says „56 alkalmazás" in
the post drafts, and the post scheduled for 2026-10-12 carries that number. It is already written and
the brief forbids editing posted text, so it stays — the next post should say 58.
## 2026-10-08 (evening) — every app logo white; five logo sets renamed to the catalog's names
- **Seven coloured logos made white like the other 49** (operator request): Mealie (one fill → white), Homebox (white
line drawing), Dawarich, Komga, Radicale, Recipe Importer (an in-file `feColorMatrix` filter: coloured and dark parts
white, white parts see-through; Dawarich keeps only its route, Recipe Importer keeps the white cloud), SparkyFitness
(PNG, same rule). Checked rendered in headless Chrome against the white logos. These files are also the dashboard's
logos (the controller and hub builds copy `*-logo.*` from here).
- **Renamed to the catalog slug** (the dashboard asks for `-logo.svg` / `-screenshot-N.webp`, so these five
showed the grey placeholder and no pictures there): `crafty` → `crafty-controller`, `grampsweb` → `gramps-web`,
`homeassistant` → `home-assistant`, `plantit` → `plant-it`, `uptimekuma` → `uptime-kuma` (24 files, `git mv`); 40
references each in `alkalmazasok.html` and `en/apps.html` (paths and `data-gallery` set names).
## 2026-10-08 (late afternoon) — one picture viewer for the whole site
- **`assets/gallery.js`** — the viewer that lived twice inline on the two apps pages is one shared file now (`defer`,
`?v=2` — v2 keeps focus inside the viewer when the last „next" turns off), its markup built by the script. The dashboard pictures (home and technology, both languages) open in it too,
as one set: Launcher → Apps → an app → Backups.
- **A set is declared, not guessed:** every picture is a real ``; an app
card's further pictures are hidden links in the card. The old probing for `-screenshot-N.webp` files is gone (no
request for a picture that is not in the page). JavaScript off: the link opens the picture, as before.
- **New: a click or tap on the big picture closes the viewer** (the close button, Esc and a click beside it still do);
a swipe changes the picture and does not close. Labels follow ``; focus goes to the viewer and back to the
clicked picture; the page does not scroll behind it.
- `site.css`: the `.lightbox-…` rules are no longer scoped to the apps page; `?v=4` → `?v=5` on all sixteen pages.
- Gate 20 (`scripts/CHANGELOG.md`).
## 2026-10-08 (afternoon) — the dashboard, shown
- **A new section after „Mit tud a doboz ma?" / „What the box does today"**: „Így néz ki a vezérlőpult" / „What the
Dashboard looks like" — four real screenshots (Launcher, Apps, an app's page, Backup → Apps), each with a one-line
caption; the technology page's dashboard card gets the Apps and Backup pictures. Hungarian pages show the Hungarian
dashboard, English pages the English one.
- Taken on demo-hp's household guest (controller 0.303.0, no warnings, last night's backups OK); 1440 × 900 WebP,
31–83 KB each; `loading="lazy"`, `width`/`height` set, each links to its full-size picture (no script).
- `site.css`: `.dash-grid` / `.dash-shot` (two per row, one below 700 px); `?v=3` → `?v=4` on all sixteen pages.
- Gate 19: a page may only show dashboard pictures in its own language (decoy seen failing first).
- Evidence, captions-to-capability rows and the privacy scan: `documentation/audits/website-dashboard-2026-10-08/`.
## 2026-10-08 — the FAQ's GDPR answer tells the truth about where copies and traffic go (R-900; operator approved the text in chat)
- `gyik.html` and `en/faq.html`, the GDPR answer, both the visible text and its structured-data copy: the line „az adataid a
saját infrastruktúrádon vannak — nem harmadik félnél" / „not with a third party" is replaced. It now says the data lives
on the household's own box; backup copies are encrypted on the box before they leave and stored at Hetzner in the EU
(Germany), where the provider cannot read them; remote access goes through Cloudflare, which could technically see that
traffic; small businesses are pointed to the privacy notice (not published yet, so no link). The „not lawyers" line
stays. Searched the rest of the site (ASCII fragments, positive control „Hetzner" = 2 per page): no other page makes
the claim.
## 2026-10-08 (later) — the language switch becomes a globe, like the dashboard's
- The text link in every page's nav („English" / „Magyar") is replaced by a **globe** (`i-globe` from the sprite): a
`` whose list names each language in its own language — Magyar, English, in that order on every page. The
page's own language is marked (bold, a blue rule, `aria-current="true"`); the other item goes to the twin page.
`aria-label`/`title` „Nyelv" / „Language". Works with JavaScript off; no script added (the controller adds none).
- Phone: inside the opened menu the globe is the last item and its list opens in place.
- `site.css`: the globe's rules (desktop and the ≤900 px menu); `?v=2` → `?v=3` on all sixteen pages. There was no
`.lang-switch` rule to retire — the text switch was unstyled.
- `404.html` and the hidden prices page carry the globe too (their foreign item points at `/en/`): the shared nav
must compare equal across the Hungarian set, so they keep what every page carries.
- Gates: the globe replaces `SWITCH_RE` in gates 3 and 13 (`scripts/CHANGELOG.md`).
## 2026-10-08 — the website catches up with the product: true numbers, the missing apps, an English twin of every page
The last content refresh was 2026-07-18. Every claim on the eight public Hungarian pages was checked again against
`documentation/architecture/00-capability-map.md` (and `07`, `09`, `10`, the catalog, the licence read) — the
table is `documentation/audits/website-refresh-2026-10-08/claims.md`. No redesign; the July tone and layout stay.
- **One app count, measured: 56.** The catalog has 58 templates; `plant-it` (abandoned) and `wger` (hidden) are
not offered to a household (`visibleCatalogStacks`). „53" and „több mint 45" are gone from every page, title,
meta tag and JSON-LD (`numberOfItems` read 45).
- **„100% nyílt forráskódú" was false.** The licence read (`audits/licences-2026-10-02/TABLE.md`): Plex and Emby are
proprietary; n8n, Outline, Tandoor and SparkyFitness carry restricted licences; Recipe Importer is Felhom's own.
Now „szinte mind"; each exception carries its own badge (*Zárt forráskód* / *Korlátozott licenc* /
*Felhom saját*); the stat reads 49 open source.
- **The apps page shows what a household can install.** Plant-it and wger cards cut; ten cards added (Dawarich,
Docmost, Grimmory, Homebox, Karakeep, Mealie, MeTube, Radicale, Recipe Importer, SparkyFitness), Hungarian
from the catalog's own text. FileBrowser stays, badged *Beépített* (it is on every box, not in the catalog).
Calibre-web → Calibre-Web Automated (the image the catalog ships). Twelve logos pointed at a missing `.svg`
and fell back to `.png` through an `onerror` — they point at the `.png` now.
- **Claims cut or softened** (no capability row): firewall/Fail2ban/geo-blocking/WireGuard-for-households, RAID,
„pillanatkép minden változtatás előtt" (the update path takes a backup and undoes itself — that is now said),
„egy új gépre visszaállítható", the „önálló modell", „bármilyen nyílt forráskódú alkalmazás telepíthető",
household VPN, „soha nem vész el" ×4, the off-site „havi pár száz forint" (the operator's own price is per
100 GB), „TV-re streamelés hamarosan" (now „még nincs").
- **Added, each on a PROVEN-LIVE row:** backups on three levels (on the box, a second drive, encrypted off-site);
careful app updates (tested versions only, a backup first, the box undoes a failed update); the dashboard in
Hungarian or English; OS security updates (the kernel lane is not claimed).
- **`technologiak.html` showed a file-dump footer** („Summary: 13 files included, 218 skipped") under ``
— removed; a gate now refuses text after `