diff --git a/CLAUDE.md b/CLAUDE.md
index 63a52eb..fa65a88 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -69,6 +69,7 @@ The frontend was originally desktop-only (zero `@media` queries, fixed 228px sid
- **Glass design system**: `:root` defines a dedicated token set — `--glass`/`--glass-strong` (translucent white fills), `--glass-border`, `--glass-blur`, `--glass-shadow`/`--glass-shadow-lg`, plus four `--bento-*` gradient tokens (mint/lavender/peach/rose) for tile accents. `body` has a fixed multi-blob `radial-gradient` background (`background-attachment:fixed`) that the translucent, `backdrop-filter:blur(...)` cards/sidebar/topbar/modal/login-box float over. Regular form inputs stay solid (`var(--surface)`, opaque white) — only container-level chrome (`.card`, `.modal`, `.sb`, `.topbar`, `.lo-box`) is glassy, intentionally, for text legibility. Always pair `backdrop-filter` with `-webkit-backdrop-filter` (Safari).
- **Dashboard is a real Bento grid**, not just a relabeled stat row: `.bento` is a 4-column CSS grid with **explicit** `grid-column`/`grid-row` line placement per tile class (`.bento-stat`, `.bento-hero`, `.bento-aufg`, `.bento-quick`) — deliberately not relying on grid auto-placement, which does not reliably fill remaining same-row cells the way you'd expect when items of different spans are mixed. If you add/resize tiles, keep using explicit line numbers (or verify auto-placement with the debug technique below) rather than assuming `span N` will pack tiles the way you expect.
- **Responsive tables → cards**: any live-UI (non-PDF-export) table that needs to stay usable at phone width gets `class="tw rtable"` on its wrapper and `data-label="…"` on every `
`. Below 700px, `.rtable` CSS turns each `
` into its own glass card (label stacked above value per cell, via `td[data-label]::before{content:attr(data-label)}`) instead of squeezing table columns. Applied to: Dashboard's recent-patients table, `renderPT` (Patientenliste), `pgAufgaben`, `renderAdminDash`'s Konten table, and the Patientenakte Anträge table. Follow this pattern for any new data table — don't ship a raw `
` without it.
+- **Accordion on the card view**: within `.rtable`, exactly one row is expanded at a time — the rest collapse to a single header line (`td.rt-head`, marked explicitly per table since it's usually the first `data-label` cell) and stack tightly, so scanning many rows needs far less scrolling. `rtInit()` (shared helper, defined near `escH`) wires this up: on load the first row gets `.rt-open`; clicking any row's header toggles it open and closes the others (clicks on nested `button,a,select,input,textarea,.tl` are ignored so action buttons/links inside a row still work independently of the accordion). **Every function that renders an `.rtable` must call `rtInit()` after the DOM is in place** (see `pgDash`, `renderPT`, `pgAufgaben`, `renderAdminDash`, `loadPat`) — a new table using this pattern that forgets the call will render but never expand/collapse. Cells without `data-label` (action-button columns) are never hidden by the accordion, so those buttons stay reachable even on a collapsed row. The `.rt-chev` chevron icon is `display:none` by default and only shown inside the `max-width:700px` breakpoint — without that base rule it leaks into the plain desktop/tablet `
` as a stray icon.
- **Mobile/tablet nav**: below 900px the `.sb` sidebar becomes a fixed off-canvas panel (`transform:translateX(-100%)`, slides in via `.sb.open`), toggled by a hamburger button (`#sb-toggle`, only visible in that breakpoint) and a `#sb-backdrop` overlay that closes it on tap. `toggleSidebar()`/`closeSidebar()` manage this; every nav-item click auto-closes it. Form grids (`.fg.c2/.c3`), stat grids (`.g4`), and the bento grid collapse to fewer columns at 900px/700px/560px. Modals go full-screen below 560px. Form inputs are forced to `font-size:16px` on phones to stop iOS Safari's auto-zoom-on-focus.
- **Verification gotcha #1 — internal scroll**: `.content` scrolls internally (`overflow-y:auto` inside a `height:100vh` shell), so Playwright's `page.screenshot({fullPage:true})` does **not** capture content below the fold — only the viewport. Scroll `.content` itself (`document.querySelector('.content').scrollTop = ...`) before screenshotting to see the rest.
- **Verification gotcha #2 — stale template cache**: `start.py` runs with `debug=False`, so Flask's `TEMPLATES_AUTO_RELOAD` is off and Jinja caches the compiled `index.html` **in memory for the life of the process**, from the first request after startup. Editing the template while a `python start.py` process is still running from before your edit is invisible to the browser no matter how many times you reload — you'll see stale HTML/JS and it's easy to misdiagnose as a CSS/JS bug. **Always restart the server after editing `templates/index.html`** before taking verification screenshots or you'll debug a ghost.
diff --git a/pflegepilot_alpha_v2/pflegepilot/templates/index.html b/pflegepilot_alpha_v2/pflegepilot/templates/index.html
index 19b0c2b..61a02a5 100644
--- a/pflegepilot_alpha_v2/pflegepilot/templates/index.html
+++ b/pflegepilot_alpha_v2/pflegepilot/templates/index.html
@@ -154,15 +154,26 @@ body{
.b-out{background:transparent;border:1px solid var(--border2);color:var(--muted)}
.tw{overflow-x:auto}
/* ── Responsive Tabellen: werden unter 700px zu Karten (rtable) ── */
+.rt-chev{display:none}
@media (max-width:700px){
.rtable table,.rtable thead,.rtable tbody,.rtable tr,.rtable td{display:block;width:100%}
.rtable thead{display:none}
- .rtable tr{background:var(--glass);-webkit-backdrop-filter:blur(var(--glass-blur));backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);border-radius:var(--r);margin-bottom:10px;padding:4px 12px;box-shadow:var(--glass-shadow)}
+ .rtable tr{background:var(--glass);-webkit-backdrop-filter:blur(var(--glass-blur));backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);border-radius:var(--r);margin-bottom:6px;padding:10px 12px;box-shadow:var(--glass-shadow);cursor:pointer}
.rtable tr:last-child{margin-bottom:0}
.rtable td{border:none;border-bottom:1px solid var(--border);padding:8px 0}
.rtable td:last-child{border-bottom:none}
.rtable td:empty{display:none}
.rtable td[data-label]::before{content:attr(data-label);display:block;font-size:10px;font-weight:600;color:var(--hint);text-transform:uppercase;letter-spacing:.04em;margin-bottom:3px}
+ /* Akkordeon: nur die offene Karte zeigt alle Felder, der Rest ist auf
+ die Kopfzeile zusammengeklappt und stapelt sich eng - weniger Scrollen. */
+ .rtable tr td[data-label]{display:none}
+ .rtable tr td.rt-head{display:flex!important;align-items:center;justify-content:space-between;gap:8px;border-bottom:none;padding:0}
+ .rtable tr td.rt-head::before{display:none}
+ .rtable tr .rt-chev{display:inline-block;font-size:16px;color:var(--hint);transition:transform .18s;flex-shrink:0}
+ .rtable tr.rt-open{padding-bottom:2px;box-shadow:var(--glass-shadow-lg);border-color:var(--green)}
+ .rtable tr.rt-open td[data-label]{display:block}
+ .rtable tr.rt-open td.rt-head{border-bottom:1px solid var(--border);padding:0 0 8px;margin-bottom:6px}
+ .rtable tr.rt-open .rt-chev{transform:rotate(180deg);color:var(--green)}
}
table{width:100%;border-collapse:collapse}
th{text-align:left;padding:8px 11px;font-size:11.5px;font-weight:500;color:var(--muted);border-bottom:1px solid var(--border)}
@@ -452,6 +463,24 @@ function toFilename(s){return(s||'').replace(/ä/g,'ae').replace(/ö/g,'oe').rep
function isoDate(){return new Date().toISOString().slice(0,10);}
function toast(m,ok=true){const t=document.createElement('div');t.className='toast';t.innerHTML=''+m;document.body.appendChild(t);setTimeout(()=>t.remove(),2800);}
function escH(s){return(s||'').replace(/&/g,'&').replace(//g,'>');}
+// Responsive Tabellen-Akkordeon (Mobile/Tablet): erste Karte offen, Rest
+// zugeklappt/gestapelt; Klick auf eine Karte öffnet sie und schliesst die
+// anderen. Nach jedem rtable-Render aufrufen (Filter/Refresh bauen neue
+//