# Zeitstrahl grouped-view layout redesign **Date:** 2026-06-15 **Feature:** #827 (regroup `/zeitstrahl` by Ereignis/Thema) — layout follow-up on PR #847 **Status:** Approved (brainstorm), pending implementation plan > The REQ contract for #827 lives in the Gitea issue body (and the amendment comment of > 2026-06-15). This document records the **layout/visual design** agreed in the visual > brainstorm and the REQ deltas it implies. Mockups: `.superpowers/brainstorm/*/content/`. ## Problem The first grouped-view implementation (PR #847) fixed the flood and the duplicate event title, but two issues remained on review of the live view: 1. **Weak belonging.** A clustered event's letters dropped below its centered pill as a full-width block with only a thin left rail. The connection between an event and its letters read weakly — the eye couldn't tell the letters belonged to the pill above. 2. **Layout inconsistency.** In Datum mode letters alternate left/right of the centered spine (events/density centered). In grouped mode the letters became full-width, breaking that rhythm with no clear reason. ## Decision: a cluster is one contained card A clustered event (Ereignis) or root tag (Thema) renders as **one bordered card** whose header is the event/tag itself and whose body holds that cluster's letters. Belonging becomes structural (a single container), not positional guesswork. This replaces the full-width block. ### Ereignis mode, per year band 1. **Derived life-events** (Geburt/Tod/Heirat, `abgeleitet`) never cluster — they carry no document links, so they are always **plain axis fixtures, unchanged from Datum mode**. A **world-band** (`historisch`) is normally letterless and stays a plain band; on the rare occasion a historical event has linked letters it follows rule 2 (becomes a card). 2. **A curated event (PERSONAL or HISTORICAL) with letters in this band** → one mint-bordered card: - **Header** = the event's glyph + title + date + `kuratiert` + edit-✎ + count (the pill's content, laid out as a header bar). This *replaces* the separate floating pill for that event in this band — killing the duplicate title. - **Body** = the cluster's letters, **first 5 shown, then a "+ N weitere Briefe anzeigen" toggle** that expands/collapses the rest. Letters use the compact `LetterCard` variant. 3. **A curated event with no letters in this band** → stays a plain centered pill (no empty card). 4. **A curated event whose letters fall in a different year than its pill** → those letters form a labeled card in *their* year (header = event name as text, no ✎/pill since the pill lives elsewhere); the pill stays in its own band. No adjacent duplication. 5. **Leftover letters** (linked to no surviving curated event) → a collapsed neutral, dashed **"✉ N Briefe ohne Ereignis · anzeigen ›"** drawer. Clicking expands to the same first-5 + show-more list. No preview letters until opened. ### Thema mode Identical shape. Each card's header is the **tinted root-tag chip** (`● Krieg · 24`, `BucketHeaderChip`, fixed-ink label per the contrast fix) instead of an event pill; there is no axis pill for a tag, so every tag cluster is a standalone card. The per-letter `TagChip` stays suppressed inside its own card (REQ-017). The leftover drawer reads **"Ohne Thema"**. ### Layout / spine - Cluster cards are **centered on the spine** (like events already are), not full-width-flush — consistent with how grouped units (events) relate to the axis. Individual chronological letters keep alternating left/right only in **Datum** mode. - Each card carries a colour left rail: **mint** for an Ereignis cluster, the **tag colour** for a Thema cluster, **neutral dashed** for the leftover drawer. ## Components affected - `LetterBucket.svelte` — becomes the contained card: header slot (pill-content / tag chip / drawer label / cross-year text label) + body with the first-5 cap and the show-more toggle. Drop the `YearLetterStrip` (sparkline) branch from grouped mode. - `YearBand.svelte` — in Ereignis mode, a same-year curated event renders *as* the card header (merge pill into the card) instead of pill-then-nested-bucket; derived/world/letterless events stay plain; cross-year clusters and the leftover drawer render after the axis entries. - `LetterCard.svelte` — compact variant already exists (PR #847); reused inside cards. - `BucketHeaderChip.svelte` — reused as the Thema card header (contrast fix already shipped). - `timelineGrouping.ts` — the first-visible cap (`CLUSTER_PREVIEW = 5`) replaces `BUCKET_DENSE_THRESHOLD`; helpers unchanged otherwise. - Possibly a small `ClusterCard`/header sub-component if `LetterBucket` grows too large. ## REQ deltas (to fold into issue #827) - **REQ-001 (amended):** derived life-events, world-bands, and *letterless* curated event pills render identically across modes; a curated event **that has letters** renders as its cluster card's header in grouped mode (no longer byte-identical to its Datum pill). Every event keeps its spine position (year). - **REQ-003 / REQ-014 (amended):** event-clustered letters live inside a contained card; the header is the event (same-year) or a text label (cross-year). First 5 shown + show-more. - **REQ-020 (amended):** grouped clusters are contained colour-railed cards with a first-5 preview + show-more toggle; the leftover bin is a collapsed count-only drawer. The month-density `YearLetterStrip` is **no longer used in grouped mode** (still used in Datum dense years). ## Out of scope - Datum mode (untouched — keeps the alternating-axis zigzag and the >12 sparkline strip). - Backend / DTO (`linkedEventId` and root-tag fields already shipped; no change). - New i18n beyond a show-more / drawer label string set. ## Testing approach TDD per component, mirroring PR #847: `LetterBucket` (card header variants, first-5 cap, show-more expand/collapse, drawer collapsed-by-default, colour rail), `YearBand` (same-year merge = no duplicate title; cross-year keeps a label; derived/world pills unchanged), and the route spec for the assembled view. Run targeted `--project=client` / `--project=server` specs only.