diff --git a/CODE_GUIDELINES.md b/CODE_GUIDELINES.md
index 50c9eca..68e7887 100644
--- a/CODE_GUIDELINES.md
+++ b/CODE_GUIDELINES.md
@@ -60,6 +60,9 @@ We are building a membership management system (Mila) using the following techno
7. [Documentation Standards](#7-documentation-standards)
8. [Accessibility Guidelines](#8-accessibility-guidelines)
+**Related documents:**
+- **UI / UX:** [`DESIGN_DUIDELINES.md`](../DESIGN_DUIDELINES.md) defines visual and interaction consistency: use of CoreComponents (no raw DaisyUI in views), page skeleton (`<.header>`, `mt-6 space-y-6`), typography, buttons, forms, tables, flash/toast, and microcopy (e.g. German "du" and glossary). Follow "components first" and semantic variants instead of hard-coded colors.
+
---
## 1. Setup and Architectural Conventions
diff --git a/DESIGN_DUIDELINES.md b/DESIGN_DUIDELINES.md
new file mode 100644
index 0000000..b0372ef
--- /dev/null
+++ b/DESIGN_DUIDELINES.md
@@ -0,0 +1,361 @@
+# UI Design Guidelines (Mila / Phoenix LiveView + DaisyUI)
+
+## Purpose
+This document defines Mila’s **UI system** to ensure **UX consistency**, **accessibility**, and **maintainability** across Phoenix LiveView pages:
+
+- consistent DaisyUI usage
+- typography & spacing
+- button intent & labeling
+- list/search/filter UX
+- tables behavior (row click, tooltips, alignment)
+- flash/toast UX (position, stacking, auto-dismiss, tones)
+- standard page skeletons (index/detail/form)
+- microcopy conventions (German “du” tone)
+
+> Engineering practices (LiveView load budget, testing, security, etc.) are defined in `docs/CODE_GUIDELINES.md`.
+> This document focuses on **visual + UX** consistency and references engineering rules where needed.
+
+---
+
+## 1) Principles
+
+### 1.1 Components first (no raw DaisyUI classes in views)
+- **MUST:** Use `MvWeb.CoreComponents` (e.g. `<.button>`, `<.header>`, `<.table>`, `<.input>`, `<.flash_group>`, `<.form_section>`).
+- **MUST NOT:** Write DaisyUI component classes directly in LiveViews/HEEX (e.g. `btn`, `alert`, `table`, `input`, `select`, `tooltip`) unless you are implementing them **inside** CoreComponents.
+- **MAY:** Use Tailwind for layout only: `flex`, `grid`, `gap-*`, `p-*`, `max-w-*`, `sm:*`, etc.
+
+### 1.2 DaisyUI for look, Tailwind for layout
+- DaisyUI: component visuals + semantic variants (`btn-primary`, `alert-error`, `badge`, `tooltip`).
+- Tailwind: spacing, alignment, responsiveness.
+
+### 1.3 Semantics over hard-coded colors
+- **MUST NOT:** Use “status colors” in views (`bg-green-500`, `text-blue-500`, …).
+- **MUST:** Express intent via component props / DaisyUI semantic variants.
+
+---
+
+## 2) Page Skeleton & “Chrome” (mandatory)
+
+### 2.1 Standard page layout
+Every authenticated page should follow the same structure:
+
+1) `<.header>` (title + optional subtitle + actions)
+2) content area with consistent vertical rhythm (`mt-6 space-y-6`)
+3) optional footer actions for forms
+
+**MUST:** Use `<.header>` on every page (except login/public pages).
+**SHOULD:** Put short explanations into `<:subtitle>` rather than sprinkling random text blocks.
+
+**Template:**
+```heex
+<.header>
+ Title
+ <:subtitle>Short explanation of what the page is for.
+ <:actions>
+ <.button variant="primary" navigate={...}>Primary action
+
+
+
+
+
+
+
+## 3) Typography (system)
+
+Use these standard roles:
+
+| Role | Use | Class |
+|---|---|---|
+| Page title (H1) | main page title | `text-xl font-semibold leading-8` |
+| Subtitle | helper under title | `text-sm text-base-content/70` |
+| Section title (H2) | section headings | `text-lg font-semibold` |
+| Helper text | under inputs | `text-sm text-base-content/70` |
+| Fine print | small hints | `text-xs text-base-content/60` |
+| Empty state | no data | `text-base-content/60 italic` |
+| Destructive text | danger | `text-error` |
+
+**MUST:** Page titles via `<.header>`.
+**MUST:** Section titles via `<.form_section title="…">` (for forms) or a consistent section wrapper (if you introduce a `<.card>` later).
+
+---
+
+## 4) States: Loading, Empty, Error (mandatory consistency)
+
+### 4.1 Loading state
+- **MUST:** Show a consistent loading indicator when data is not ready.
+- **MUST NOT:** Render empty states while loading (avoid flicker).
+- **SHOULD:** Prefer “skeleton rows” for tables or a spinner in content area.
+
+### 4.2 Empty state pattern
+Empty states must be consistent:
+- short message
+- optional primary CTA (“Create …”)
+- optional secondary help link
+
+**Example:**
+```heex
+
+
No members yet.
+ <.button variant="primary" navigate={~p"/members/new"}>Create member
+
+
+### 4.3 Error state pattern
+- **MUST:** Use flash/toast for global errors.
+- **SHOULD:** Also show inline error state near the relevant content area if the page cannot proceed.
+
+---
+
+## 5) Buttons (intent, labels, variants)
+
+### 5.1 Decision rule: action vs status
+- **MUST:** Button labels describe **actions** (verb-first):
+ - ✅ Save, Create member, Send invite, Import CSV
+ - ❌ Active, Success, Done (status belongs elsewhere)
+- **MUST:** Status belongs in badges/labels or read-only text, not in CTAs.
+
+### 5.2 Standard variants (mandatory set)
+Buttons must be rendered via `<.button>` and mapped to DaisyUI internally.
+
+**Supported variants:**
+- `primary` (main CTA)
+- `secondary` (supporting)
+- `neutral` (cancel/back)
+- `ghost` (low emphasis; table/toolbars)
+- `outline` (alternative CTA)
+- `danger` (destructive)
+- `link` (inline; rare)
+- `icon` (icon-only)
+
+**Sizes:** `sm`, `md` (default), `lg` (rare)
+
+### 5.3 Placement rules
+- Header CTA inside `<.header><:actions>`.
+- Form footer: primary right; cancel/secondary left.
+- Tables: use `ghost`/`icon` for row actions (avoid `primary` inside rows).
+
+### 5.4 Primary vs Secondary (UX consistency rules)
+
+#### One primary action per screen
+- MUST: Each screen/section has at most one **primary** action (e.g. Save, Create, Start import).
+- SHOULD: Additional actions are secondary/neutral/ghost, not additional primary.
+
+#### Primary vs Secondary meaning
+- Primary = the most important/most common action to complete the user task.
+- Secondary = supporting actions (Cancel/Back/Edit in tool contexts), lower emphasis.
+
+#### Order and placement (choose and apply consistently)
+We follow these ordering rules:
+- MUST: Order buttons by priority: **Primary → Secondary → Tertiary**.
+- Forms: Decide once (primary-left OR primary-right) and apply everywhere.
+- Dialogs/confirmations: Place the confirmation action consistently (e.g. trailing edge, confirmation closest to edge).
+
+#### Cancel/Back consistency
+- MUST: Cancel/Back is **never** styled as primary.
+- MUST: Cancel/Back placement is consistent across the app (same side, same label).
+
+#### Implementation requirement
+- MUST: Use CoreComponents (`<.button>`) with `variant`/`size` props.
+- MUST NOT: Use ad-hoc classes like `class="secondary"` on `<.button>`; instead extend CoreComponents to support `secondary`, `neutral`, `ghost`, `danger`, etc.
+
+#### Ghost buttons (accessibility requirements)
+
+Ghost buttons are allowed for low-emphasis actions (toolbars, table actions), but:
+
+- MUST: Focus indicator is clearly visible (do not remove outlines).
+- MUST: UI contrast for the control (and meaningful icons) meets WCAG non-text contrast (≥ 3:1).
+- MUST: Icon-only ghost buttons provide an accessible name (`aria-label`) and preferably a tooltip.
+- SHOULD: Hit target is large enough for touch/motor accessibility (recommend ~44x44px).
+If these cannot be met, use `secondary`/`outline` instead of `ghost`.
+
+
+---
+
+## 6) Forms (structure + interaction rules)
+
+### 6.1 Structure
+- **MUST:** Forms are grouped into `<.form_section title="…">`.
+- **MUST:** All inputs via `<.input>`.
+
+### 6.2 Validation timing (consistent UX)
+- **MUST:** Validate on submit always.
+- **SHOULD:** Validate on change only where it helps; use debounce to avoid “error spam”.
+- **MUST:** Define a consistent “when errors appear” rule:
+ - Preferred: show field errors after first submit attempt OR after the field has been touched (pick one and apply everywhere).
+
+> Engineering note (implementation): follow LiveView load budget in `CODE_GUIDELINES.md` (no DB reads on `phx-change` by default).
+
+### 6.3 Required fields
+- **MUST:** Required fields are marked consistently (UI indicator + accessible text).
+- **SHOULD:** If required-ness is configurable via settings, display it consistently in the form.
+
+---
+
+## 7) Lists, Search & Filters (mandatory UX consistency)
+
+### 7.1 Standard filter/search bar pattern
+- **MUST:** All list pages use the same search/filter placement (choose one layout and apply everywhere).
+ - Recommended: top area above the table, aligned with page actions.
+- **MUST:** Always provide “Clear filters” when filters are active.
+- **MUST:** Filter state is reflected in URL params (so reload/back/share works consistently).
+
+### 7.2 URL behavior (UX rule)
+- Use `push_patch` for in-page state changes: filters, sorting, pagination, tabs.
+- Use `push_navigate` for actual page transitions: details, edit, new.
+
+---
+
+## 8) Tables (mandatory UX)
+
+### 8.1 Default behavior: row click opens details
+- **DEFAULT:** Clicking a row navigates to the details page.
+- **EXCEPTIONS:** Highly interactive rows may disable row-click (document why).
+
+**IMPORTANT (correctness with our `<.table>` CoreComponent):**
+Our table implementation attaches the `phx-click` to the **`
`** when `row_click` is set. That means click events bubble from inner elements up to the cell unless we stop propagation.
+
+So, for interactive elements inside a clickable row, you must **stop propagation using `Phoenix.LiveView.JS.stop_propagation/1`**, not a custom attribute.
+
+✅ Correct pattern (one click handler that both stops propagation and triggers an event):
+```heex
+<.table
+ id="members"
+ rows={@members}
+ row_click={fn m -> JS.navigate(~p"/members/#{m.id}") end}
+>
+ <:col :let={m} label="Name">
+ <%= m.last_name %>, <%= m.first_name %>
+
+
+ <:col :let={m} label="Newsletter">
+ JS.stop_propagation()}
+ />
+
+
+ <:action :let={m}>
+ <.button
+ variant="ghost"
+ size="sm"
+ navigate={~p"/members/#{m.id}/edit"}
+ phx-click={JS.stop_propagation()}
+ >
+ Edit
+
+
+
+
+Notes:
+- The checkbox uses `phx-click={JS.push(...) |> JS.stop_propagation()}` so it won’t trigger row navigation.
+- The Edit button also stops propagation to avoid accidental row navigation when clicked.
+
+### 8.2 Tooltips (mandatory where needed)
+- **MUST:** Tooltips for:
+ - icon-only actions
+ - truncated content
+ - status badges that require explanation
+- **MUST:** Provide tooltips via a shared wrapper (recommended `<.tooltip>` CoreComponent).
+- **MUST NOT:** Scatter ad-hoc tooltip markup in views.
+
+### 8.3 Alignment & density conventions
+- **MUST:** Text columns left-aligned.
+- **MUST:** Numeric columns right-aligned.
+- **MUST:** Action column right-aligned.
+- **SHOULD:** Table density is consistent:
+ - default density for most tables
+ - a single “dense” option only if needed (via a prop, not per-page random classes)
+
+### 8.4 Truncation standard
+- **MUST:** Truncate long values consistently (same max widths for name/email-like fields).
+- **MUST:** Tooltip reveals full value when truncated.
+
+---
+
+## 9) Flash / Toast messages (mandatory UX)
+
+### 9.1 Location + stacking
+- **MUST:** Position flash/toasts at the bottom of the viewport (pick bottom-right or bottom-center; be consistent).
+- **MUST:** Stack all flash messages with consistent spacing.
+- **SHOULD:** Newest appears on top.
+
+### 9.2 Auto-dismiss
+- **MUST:** Flash messages disappear automatically:
+ - info/success: 4–6s
+ - warning: 6–8s
+ - error: 8–12s (or manual dismiss for critical errors)
+- **MUST:** Keep a dismiss button for accessibility and user control.
+
+### 9.3 Variants + special “email copied”
+- Supported semantic variants: `info`, `success`, `warning`, `error`.
+- **Special case:** clipboard “Email copied” uses a **soft/light blue** tone distinct from normal info.
+- **MUST:** Model this as `tone="soft"` (or similar prop) on the flash component, not hard-coded colors in views.
+
+### 9.4 Accessibility
+- Flash must work with screen readers (live region behavior belongs in the flash component implementation).
+- See `CODE_GUIDELINES.md` Accessibility → live regions.
+
+---
+
+## 10) Mutations & feedback patterns (create/update/delete/import)
+
+### 10.1 Mutation feedback is always two-part
+For create/update/delete:
+- **MUST:** Show a toast/flash message
+- **MUST:** Show a visible UI update (navigate, row removed, values updated)
+
+No “silent success”.
+
+### 10.2 Destructive actions: one standard confirmation pattern
+- **MUST:** All destructive actions use the same confirm style and wording conventions.
+- Choose one approach and standardize:
+ - `JS.confirm("…")` everywhere (simple, consistent)
+ - or a modal component everywhere (more flexible, more work)
+
+**Recommended copy style:**
+- Title/confirm text is clear and specific (what will be deleted, consequences).
+- Buttons: `Cancel` (neutral) + `Delete` (danger).
+
+---
+
+## 11) Detail pages (consistent structure)
+
+Detail pages should not drift into random layouts.
+
+**MUST:** Use consistent structure:
+- header with primary action (Edit)
+- sections/cards for grouped info
+- “Danger zone” section at bottom for destructive actions
+
+---
+
+## 12) Navigation rules (UX consistency)
+
+- **MUST:** `push_patch` for in-page state: sorting, filtering, pagination, tabs.
+- **MUST:** `push_navigate` for page transitions: detail/edit/new.
+- **SHOULD:** Back button behavior must feel predictable (URL reflects state).
+
+---
+
+## 13) Microcopy conventions (German “du” tone + glossary)
+
+### 13.1 Tone
+- **MUST:** All German user-facing text uses informal address (“du”).
+- **MUST:** Use consistent verbs for common actions:
+ - Save: “Speichern”
+ - Cancel: “Abbrechen”
+ - Delete: “Löschen”
+ - Edit: “Bearbeiten”
+
+### 13.2 Preferred terms (starter glossary)
+- Member: “Mitglied”
+- Fee/Contribution: “Beitrag”
+- Settings: “Einstellungen”
+- Group: “Gruppe”
+- Import/Export: “Import/Export”
+- Clear filters: “Filter zurücksetzen” (use when filters are active; button label in list/filter UX)
+
+Add to this glossary when new terminology appears.
+
+---