Files
felhom.eu/website/CHANGELOG.md
T
admin 56c357c074
gates / gates (push) Successful in 6m31s
report + plan: the redesign session's record, and the order for the other pages
REPORT-redesign-2026-10-10.md (not REPORT.md: that file belongs to the kernel
night session de4a8d20 and is overwritten per session).

NEXT.md - the other pages in order with what each needs, and the traps:
  teszteles/en/testing first (the destination of every CTA, newest page)
  gyik/en/faq second, with the warning that gate 17 requires the FAQPage JSON-LD
    to EQUAL the visible answers, so every copy edit there is a two-place edit
  technologiak third ("Ipari szintu megoldasok" is the exact language the home
    page just removed)
  alkalmazasok is BLOCKED on R-929 - prose 58, page 59 cards, catalog 60
  adatkezeles/feltetelek are reviewed legal texts; a dash sweep there needs the
    operator's word separately and is not ours to take

  It also records the per-page em-dash count: 300 across 19 pages, the preview
  being the only page at zero.

STATUS.md - the operator's one screen, in plain language: the preview is waiting
on him, the two fixes that DID go live, and the two new decisions (R-931 the
missing compression, R-929 the app count).

website/CHANGELOG.md - the footer sweep and R-930, both with their measurements
and with the scope stated rather than implied.

Register 127 -> 129 (R-930, R-931 opened; none closed).
2026-10-11 00:31:14 +02:00

29 KiB
Raw Blame History

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 <title>, 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 <slug>-logo.svg / <slug>-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 <a href="/assets/…webp" data-gallery="<set>">; 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 <html lang>; 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 <details> 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 </html> — removed; a gate now refuses text after </html>.
  • 404.html — nginx's error_page 404 pointed at a page that did not exist. Hungarian first, one English line, a link home; noindex.
  • The English twin of every public page (operator ruling 2026-10-08; choice B — public at once): /en/, /en/apps, /en/technology, /en/backups, /en/faq, /en/contact, and /en/download moved onto the new English nav and footer. hreflang hu/en/x-default both ways, canonical to itself, lang="en", English JSON-LD (the FAQ's JSON-LD is now rebuilt from its visible answers on both pages — the Hungarian one had drifted from them), an English og-image-en.png (the card carries Hungarian text). The English footer says Felhom serves households in Hungary. The contact form posts to the same /api/contact with English subject labels marked „(EN)"; ?tema= takes the same values.
  • The language switch — one nav item on every page, „English" / „Magyar", pointing at the twin; it replaces the header link R-559 put on the two download pages. No redirect, no cookie.
  • sitemap.xml lists both languages with xhtml:link alternates.
  • Gates: scripts/site_gates.py gates 3 and 13–18, eleven new decoys (see scripts/CHANGELOG.md).

Published: push to main, git-sync. No site.css or icons.svg change, so no cache-bust bump.

2026-09-18 — an English download page (R-559)

  • website/en/download.html — the English twin of letoltes.html. Same installer, same checksum, same structure; <html lang="en">, its own English nav and footer, hreflang alternates both ways (x-default points at the Hungarian), and an entry in sitemap.xml.
  • letoltes.html changed by FOUR lines and nothing else: three hreflang alternates and one English link in the page header. The link is deliberately not in the nav — the nav is a shared block that site_gates.py pins across every page, and the gate convicted the first attempt, which is how the link found its right home.
  • The rest of the marketing site stays Hungarian (operator ruling 1b, 2026-09-17).
  • New gate 12: the two download pages must name the SAME installer file and the SAME checksum. Publishing an ISO now means editing a filename, a size and a 64-character hash on two pages; update one and forget the other and an English reader checks a new image against an old hash, fails, and is told by the page itself not to use the file. Red-proofed both ways.
  • en/download.html is registered in PAGES and in the new EN_PAGES set, which exempts it from the Hungarian nav/footer comparison and from nothing else.

Published: the site's normal path — push to main, git-sync picks it up in ~1–2 min. No site.css change, so no cache-bust bump was needed.

website/ changelog (newest on top)

2026-09-15 — New page: /letoltes (the installer download)

The volunteer guide sends people to felhom.eu/letoltes; the page did not exist. It now names installer 1.27.1, its size and SHA-256, how to check the sum on Linux/Mac and Windows, and — first — the disk warning: the installer erases the disk you choose, never picks one, unplug the backup drive, call the operator if unsure. noindex (it is for people holding the guide). Same skeleton as the other pages, no nav entry; added to sitemap.xml and to scripts/site_gates.py PAGES; site gate OK. Published together with the ISO (round trip verified first), so the link never pointed at a missing file.

2026-07-19 — Restored: the index grid background

The subtle grid behind the hero was not removed on purpose. It lived as a fixed body::before in index.html's inline <style> block and was dropped when bed8675 ("D3 Part 2") migrated the page onto the shared assets/site.css; dd54e4c, the commit that created site.css, has no body::before at all. A porting omission, and nothing took its place. No asset was lost — it was pure CSS (two stacked linear-gradients), so there was nothing missing from the worktree to notice.

Restored, not redesigned: same 50px cells, same 1px lines, same 3% opacity, same position:fixed / z-index:-1 so it does not scroll. One deliberate difference — the accent is the v2 --blue #0083D8 instead of the retired legacy #0088cc, which site_gates.py bans. Scoped to body.page-index, because index is the only page that ever had it.

site.css cache-bust bumped ?v=1 → ?v=2 on all seven pages (nginx caches 7 days). Verified live on desktop and in a 376px viewport: grid renders, no horizontal overflow, mobile layout unchanged.

2026-07-18 — Pre-Facebook content refresh: capability-map alignment + „Zárt teszt" landing

The site's audience changes from zero-stakes to real Hungarian households arriving from a Facebook post, mostly on phones. Every claim re-checked against documentation/architecture/00-capability-map.md; overclaims cut, the last week's shipped capabilities added. No redesign — the design language, nav, footer, and CSS are untouched.

  • Naming ruling applied — „Felhő Felügyelő" is gone (0 occurrences site-wide). The brand is Felhom; the customer-facing interface is the vezérlőpult (matching the controller login page). 14 occurrences replaced across index.html + technologiak.html, incl. <title>, meta description, keywords, og/twitter descriptions, and the JSON-LD description.
  • index.html — new „Mit tud a doboz ma?" section (8 cards, every one map-traceable): photos/documents/media, Hálózati megosztás (Windows Intéző + Mac Finder, map §E PROVEN-LIVE 2026-07-18), two-tier automatic backup, the recovery code only the customer knows (zero-knowledge wording, map §A escrow PROVEN-LIVE), 53 apps, remote monitoring + automatic updates, LAN-works-when-the-internet-is-down, restore-when-something-breaks.
  • index.html — new „Zárt teszt" section (the Facebook post's landing target): what being a tester means, and the stated limitations — one shared household password for the vezérlőpult (map §E multi-user = MISSING), TV-re streamelés hamarosan (map §E DLNA = MISSING), and an explicit "you will find bugs, that's the point". CTA wires to the existing, live contact-mailer as /kapcsolat?tema=zart-teszt; no new backend.
  • kapcsolat.html — new „Zárt teszt — jelentkezem tesztelőnek" subject option + its label mapping (mail subject Jelentkezés — zárt teszt), and a ?tema= preselect that ignores unknown values.
  • og:image was a 404 site-wide — every page pointed at /assets/og-image.png, which did not exist (only .svg did). A branded 1200×630 card is now generated from the existing logo and brand tokens, plus og:image:width/height/alt. This was load-bearing for the Facebook post: the link previously would have rendered with no image.
  • App count corrected 45+ → 53 (real catalog count: 53 *.felhom.yml templates) in index.html, technologiak.html, and the four alkalmazasok.html head tags.
  • Overclaims cut:
    • The whole Kubernetes/k3s section in technologiak.html (+ its TOC entry and the multi-node hardware tier) — no customer-facing capability-map row backs it, and it carried a bare availability promise („a szolgáltatás nem állhat le") on a page now read by recruits.
    • Tailscale VPN → WireGuard VPN (Tailscale is not what ships).
    • The RAID card → an honest two-tier backup card; the „4-8 TB (RAID)" spec row → „4-8 TB". (RAID has no map row; the shipped model is second-drive tier-2 + encrypted offsite.)
    • gyik.html multi-user answer rewritten in both copies (JSON-LD and the visible accordion — they must stay in sync): apps do have per-person accounts, the vezérlőpult has one shared household password. Previously it read „Minden családtag saját fiókot kap".
    • biztonsagimentes.html — „azonnal értesítést kapsz" softened (map §F health-degradation e-mail is IMPLEMENTED, never live-fired), and a new helyreállítási kód block stating both sides plainly: nobody else can read the remote backup, and without the code neither can we.
  • Gates: python scripts/site_gates.py green (BOM, emoji=0, nav/footer identical, analytics, no CDN, no legacy tokens, no <style>, cache-busted assets). Mobile verified by measurement at 380 px: scrollWidth == clientWidth == 365 (no horizontal scroll), CTA 275×58.

2026-07-02 — TASK-D3: design system v2 re-skin (content-preserving)

All seven pages re-skinned to the v2 language (documentation/design/design-system.md); URLs, copy, meta/SEO, analytics, and the contact form's functional markup unchanged.

  • One stylesheet: the seven near-identical embedded <style> blocks (≈120 KB combined) extracted into assets/site.css?v=1 — vendored @font-face, the v2 :root tokens, a deduped shared base, and per-page sections scoped by page-<name> body classes. Zero <style> blocks remain.
  • Self-hosted fonts: Plus Jakarta Sans + JetBrains Mono (variable woff2, latin+latin-ext, copied byte-identical from felhom-controller) served from /assets/fonts/ — the Google Fonts CDN (a GDPR exposure for a data-sovereignty product) is gone, preconnect hints included.
  • Icons: all 182 emoji replaced by a 70-symbol external Lucide sprite (/assets/icons.svg?v=1#i-name): feature tiles as .ico-tile 48px bg-2 squares, heading icons .ico-lg, inline .ico; the alkalmazasok "Open Source" green checkmark image → sprite check (.ico-yes, blue). CSS-generated ✓/✗/★ content → currentColor mask marks / plain text.
  • Nav/footer normalized across all seven pages (index's #szolgaltatasok → /#szolgaltatasok); byte-identical after the active-marker strip.
  • Visual v2: navy tokens, single 2px radius, no shadows/gradients/hover-lifts, two-tone heading kept as solid --blue-bright, prefers-reduced-motion respected.
  • Gates: scripts/site_gates.py (BOM ×7, emoji, nav/footer, analytics, no-CDN, banned tokens, style-blocks, ?v= cache-busting) — baseline 84 problems + 182 emoji → all green.
  • kapcsolat: form fields/JS/endpoint byte-identical; live TESZT submission accepted (contact-mailer [OK] Email sent, resend id logged).