| Avatar |
| Size | 40px × 40px (desktop) · 36px × 36px (mobile) | border-radius: 50% |
| Planner colour | bg --green-tint · text --green-dark | Contrast OK: #2E6E39 on #E8F5EA ≈ 6.1:1 |
| Member colour | bg --blue-tint · text --blue-dark | Contrast OK: #0C447C on #E6F1FB ≈ 7.4:1 |
| Content | First letter of first + last name (uppercase) | Max 2 characters |
| Role badge |
| Shape | border-radius: --radius-full · padding: 3px 10px | font-size: 11px · font-weight: 500 |
| Planner | bg --green-tint · color --green-dark | Label: "Planner" |
| Member | bg --blue-tint · color --blue-dark | Label: "Mitglied" |
| Invite / pending |
| Expiry badge — urgent (≤3d) | bg --yellow-tint · color --yellow-text | "Läuft ab in N Tagen" |
| Expiry badge — normal | bg --color-subtle · color --color-text-muted | "Läuft ab am DD. MMM" |
| Code font | font-family: --font-mono · font-size: 13px | Invite codes are monospace |
| Interactions |
| Remove action | Confirmation dialog required | Dialog must show member name. Irreversible — member loses access immediately. |
| Copy invite link | navigator.clipboard.writeText() | Show transient "Kopiert!" feedback (checkmark, 2s) |
| Regenerate invite | POST /household/invite — returns new code | Old code is immediately invalidated |
| Responsive |
| Desktop (≥1024px) | 224px sidebar + full content area | Active sidebar item: Mitglieder (Haushalt section) |
| Mobile (<768px) | No sidebar · bottom nav · "Einstellungen" tab active | V3 mobile uses tab bar within page, not app bottom nav tabs |