Commit Graph

6 Commits

Author SHA1 Message Date
Hermes
acaea97415 fix(locale-switcher): make flag the visual anchor (32x24, no border, no lazy load)
Martin feedback round 3: dropdown still looked 'fuerchterlich' even
with the official flag-icons. Root cause: 14px vertical padding
around an 18px-tall flag meant the flag occupied only 39% of the
trigger height and was dwarfed by whitespace. Plus a 1px black
box-shadow border made flags look 'boxy', and loading='lazy' caused
empty boxes on the four menu flags the moment the <details> opened.

Changes:
- Flag size 24x18 -> 32x24 (+78% area, ~4:3 matches flag-icons)
- Trigger padding 14px 8px -> 6px (flag now 73% of trigger width,
  55% of trigger height, was 46%/39%)
- Drop the artificial 1px black box-shadow outline on flags
- Drop border-radius on flags (real flag-icons look better as
  crisp rectangles)
- Drop object-fit: cover (no longer needed for SVG)
- Drop loading='lazy' and decoding='async' (4 small SVGs, must
  be ready the moment <details> opens, not flash empty boxes)
- min-height: 44px restored on trigger for WCAG 2.5.5 touch target
- Menu border-radius 8 -> 10px, padding tightened, font-size 0.85
  -> 0.9rem for label legibility
- Two-layer box-shadow on menu for subtle elevation
2026-06-05 17:05:01 +00:00
Hermes
391985cd42 fix(flags): replace hand-coded inline SVGs with official flag-icons assets
The previous inline flag SVGs were visually broken — most notably the
'en' Union Jack, which was reduced to a single X plus a cross and did
not resemble the real flag at all. The 'de' and 'ru' stripes also had
slight off-by-pixel rounding errors.

Switched to lipis/flag-icons (CC-BY 4.0) shipped as static files under
public/img/flags/. These are the canonical, professionally-designed
flag icons with correct proportions and all the details of the real
flags. Loaded via plain <img> tags (no JS, no external CDN at
runtime, no FOUC, no extra request after the page is cached).

Locale code mapping: en -> gb (per ADR-002, en = en-GB). Unknown
locales fall back to a 1x1 transparent gif so the layout stays
intact.
2026-06-04 19:43:23 +00:00
Hermes
08235b0faf refactor(locale-switcher): single flag-sized dropdown, drop 4-inline-flag UI
The nav previously showed 4 inline flag buttons (DE/EN/UK/RU) on desktop
and a details-based dropdown on mobile. Martin asked for one dropdown with
a trigger the size of a single flag, and the 4 inline flags to go away.

- LocaleSwitcher: render a single <details class='locale-switcher'>
  everywhere; trigger is one flag + tiny caret; menu lists all 4 with labels.
- Drop the 4-inline <ul> and the locale-switcher-mobile duplicate.
- CSS: replace both blocks with one compact dropdown (flag-sized trigger,
  44px touch target via padding, scrolled/transparent-nav variants).
- Tests: assert 4 menu options, 5 flag SVGs, single <details> dropdown,
  active locale is a <span aria-current>, others are <a> with hreflang.
- 141/141 PHPUnit green.
2026-06-04 18:24:36 +00:00
Hermes
7dd8023222 -m 2026-06-04 17:23:49 +00:00
Hermes
0186de90ec feat(i18n): responsive locale-switcher with SVG flags (closes #75) 2026-06-04 09:44:40 +00:00
Hermes
ce21242308 feat(i18n): LocaleController switcher with open-redirect protection (closes #73)
- App\Controllers\LocaleController: GET /locale?set=xx&return=/path
  - Sets 1-year cookie (HttpOnly=false for SSR, SameSite=Lax, Secure on HTTPS)
  - 302 redirect to explicit return URL > Referer > /
  - Pure buildResponse() helper for unit tests (no headers/exit)
  - current() helper: resolves locale from $_GET/$_COOKIE/Accept-Language
- safeRedirect: rejects absolute URLs, protocol-relative (//evil.com),
  backslash tricks (\\evil.com), javascript:/data: schemes
- 28 PHPUnit tests (LocaleControllerTest), all green
- Total project tests now: 92
2026-06-04 08:57:33 +00:00