docs: minimalist UI redesign proposal

Per-screen audit + 6 design principles + per-screen mockups + commit-by-commit
implementation plan + 7 open questions.

Boldest moves: collapse the 5-button-per-row admin list into a hover-revealed
⋯ menu with clickable status pill; fold the standalone Share section into the
detail-page header as an inline link strip; drop the JSON-questions textarea
from /new behind a <details> disclosure so the common path reads as four
inputs and a button.

No code touched — design only. Awaiting m's go before coder shift.
This commit is contained in:
mAi
2026-05-06 12:16:18 +02:00
parent 3d03ee0c85
commit 301cec817a

706
docs/plans/ui-redesign.md Normal file
View File

@@ -0,0 +1,706 @@
# fdbck — minimalist UI redesign
**Status:** design proposal, not yet approved.
**Branch:** `mai/cronus/fdbck-minimalist-ui`.
**Author:** cronus, 2026-05-06.
m's brief: *"While our app is quite simple, the layout of it seems overly complex
and crowded. I want clearer separation (by negative space) between the different
elements and smarter control buttons for a smooth UX."*
The app is already small (1 stylesheet, 2 reusable components, 5 routes). The
problem isn't features — it's that the existing screens fight minimalism with
*always-visible action rows*, *redundant copy*, *inline `style="..."` patches*,
and *tight vertical rhythm*. This doc proposes per-screen edits that hold
features constant but trade visible buttons for whitespace and progressive
disclosure.
---
## 1. Audit
### 1.1 `/` (landing)
```
┌────────────────────────────────────────┐
│ fdbck │ ← 1.75rem h1
│ Private feedback forms and live chat… │
│ │
│ This page is only reachable through… │
│ [ Admin sign-in ] │ ← ghost button
└────────────────────────────────────────┘
```
- Already close to minimalist — 20 lines of markup, two paragraphs, one ghost
button. Mostly fine.
- The wordmark `fdbck` is the brand moment but renders at the same size as
every other page h1 (`1.75rem`). It should *feel* like a logo on the landing
page, not a generic heading.
- Two paragraphs ("Private feedback forms…" / "This page is only reachable…")
partly say the same thing. The second one is a near-tautology — the user is
already on the page, so "you got here through a private link" is implicit.
- Vertical rhythm is tight: `1.5rem` between subtitle and section, then the
button sits right under one short sentence.
- Tiny: a marketing-blank landing for a tool whose CTA is "sign in" feels
hollow. Either lean further into emptiness (just the wordmark + sign-in) or
add one line of confidence-building text. We'll lean into emptiness.
### 1.2 `/login`
```
┌────────────────────────────────────────┐
│ Sign in │
│ Admin access only. │
│ │
│ Email [______________] │
│ Password [______________] │
│ [ Sign in → ] │
└────────────────────────────────────────┘
```
- "Sign in" + "Admin access only" is mild redundancy — the page is the form.
- Error banner sits *between* the password field and the submit button, which
pushes the button down on error and feels like a layout glitch. Better
position: above the form (page-level error) or beneath the button as an
inline string.
- Two fields, one button, no dark patterns — already minimalist. Just needs
more vertical breathing room and a quieter subtitle (or none).
### 1.3 `/admin/feedback` (list)
```
┌──────────────────────────────────────────────────────────────────┐
│ Feedback forms [ + New form ] │
│ Collect feedback through forms or live chat. Share a private… │
│ │
│ Your forms (4) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Title (link) [Form+chat] [open] │ │
│ │ 12 responses · 7 messages · created 2026-05-01 │ │
│ │ /f/long-slug-shown-raw │ │
│ │ [Edit] [Copy link] [Open] [Close] [Delete] ← 5 buttons │ │
│ └──────────────────────────────────────────────────────────┘ │
│ … │
└──────────────────────────────────────────────────────────────────┘
```
- **The biggest offender.** Five always-visible buttons per row (Edit, Copy
link, Open, Close/Reopen, Delete) wrap onto multiple lines on narrow widths.
Even on desktop they read as a noisy strip.
- Each row has *border + shadow + bg + padding + status pill + mode pill +
raw slug + meta line + button strip*. Nine visual objects per row.
- Inline `style="…"` everywhere (`+page.svelte:108-156`). Should be classes in
`feedback.css` so dark-mode and rhythm tokens stay consistent.
- The raw `/f/<slug>` line is shown but has no purpose for the admin — they
use Copy link or Open. It's just text noise.
- Header repeats the page title in the body (`<h1>Feedback forms</h1>`) and
then the section heading (`<h2>Your forms (N)</h2>`). The H2 mostly
duplicates the H1, just with a count.
### 1.4 `/admin/feedback/new`
```
┌──────────────────────────────────────────────────────────────────┐
│ [← All forms] │
│ Create a new form │
│ Set up a feedback form, a live chat session, or both. You'll… │
│ │
│ Title [______________________________] │
│ Description [______________________________] │
│ ☑ Enable live chat │
│ Questions (JSON, optional) [ + Insert sample ] │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ { … 14-row JSON textarea, monospace … } │ │
│ └──────────────────────────────────────────────────────────┘ │
│ Leave empty for chat-only feedback. You can edit questions… │
│ │
│ [ ✓ Create form ] │
└──────────────────────────────────────────────────────────────────┘
```
- The JSON textarea is a *power-user escape hatch* dropped into the same
surface as a beginner-friendly title/description form. It dominates the
page (14 rows, monospace font), even though the visual builder on the
detail page is the recommended path.
- "Insert sample" sits *to the right* of the label, inside the field's
header — visually clever but also noise.
- The chat checkbox is a single inline item floating in its own block. It
looks afterthought-y. (It also reuses `.fb-option-row` styling, which is
meant for question options.)
- Helper text under the JSON is good, but it's the *third* descriptive
paragraph on the page (`<p>Set up a feedback form…</p>`,
`placeholder="…"`, `<div class="fb-question__help">`).
### 1.5 `/admin/feedback/[id]` (detail)
```
┌────────────────────────────────────────────────────────────────────────┐
│ [← All forms] │
│ My session feedback │
│ Some optional description text shown if present. │
│ [open] /f/long-slug [Copy link] [Preview] [Close] [CSV] [JSON] [Delete] ← 8 chips/buttons in one row
│ │
│ ┌── Share ─────────────────────────────────────────────────────────┐ │
│ │ Memorable short link — resolves to /f/long-slug. │ │
│ │ https://msbls.de/vote [ Copy ] [ Open ↗ ] │ │
│ │ ▸ Replace with a different short link │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ [ Chat (3) ] [ Results (12) ] [ Responses (12) ] [ Edit ] │
│ …active tab body… │
└────────────────────────────────────────────────────────────────────────┘
```
- **Header is the densest surface in the app.** Eight clickable controls in a
flex-wrap row: status pill, raw slug, Copy link, Preview, Close/Reopen,
CSV, JSON, Delete. On a 1024px viewport this wraps onto two lines.
- "Copy link / Preview" in the header *and* a separate Share section *and*
the slug shown raw — three different ways to access the same URL.
- CSV / JSON download buttons sit between Close and Delete — they're not
in the same gravitational tier (export is benign, Delete is nuclear), but
they look identical (both `fb-btn--ghost fb-btn--sm`).
- The Share section (recently added) was bolted onto the layout rather than
designed into it. It sits between header and tabs, breaking the "header →
tab → tab body" mental model.
- The Edit tab's form has its own internal mini-toolbar (Visual / JSON
toggle), which is correct but visually clashes with the parent tab strip
one screen up.
- Polling `setInterval(refresh, 5000)` is right; no UX change needed there.
### 1.6 `/f/[slug]` (participant)
```
┌──────────────────────────────────────────┐
│ Title │
│ Optional description │
│ [⚠ closed banner if closed] │
│ │
│ Dein Name (optional): [Anonym______] ← inline label + full-width input collide
│ │
│ ┌── Live-Feedback ──────────────────┐ │
│ │ scroll list of posts │ │
│ │ [textarea] │ │
│ │ [ Senden ] │ │
│ └───────────────────────────────────┘ │
│ │
│ ┌── Fragebogen ─────────────────────┐ │
│ │ q1 [...] │ │
│ │ q2 [...] │ │
│ │ [ Absenden ] │ │
│ └───────────────────────────────────┘ │
│ │
│ fdbck.msbls.de │
└──────────────────────────────────────────┘
```
- Already simple. Needs *more* breathing room between Chat and Form sections
— they read as two equally-weighted siblings, but in practice one of them
is what the user came for.
- The `Dein Name (optional):` label sits inline left of a full-width input
(`fb-name-row`), while every other label in the participant form is on
its own line above the input. The inline-label pattern is the only one
of its kind on this page — kill it.
- Footer `fdbck.msbls.de` is fine as a quiet trust signal.
- Closed banner uses `--color-warning` palette which reads as alert; for a
closed-form *neutral* state, a quieter visual is better.
- Locale mix: admin pages use English (`Sign in`, `Edit`, `Delete`), but the
participant page is German (`Senden`, `Absenden`, `Fragebogen`). Probably
intentional (admins are us, participants are German-speaking) — flagging
it so we don't accidentally homogenise during the redesign. **Not in
scope to change.**
---
## 2. Principles
The following six rules apply to every screen. They are the lens for §3.
1. **Whitespace over dividers.** Replace borders/shadows/dividers with
generous vertical space. The rule of thumb: if a card is bordered on a
page that's already on a coloured `--gradient-bg`, the card competes with
the page background — drop the border, keep the radius+padding, lean on
negative space. Spacing scale: `0.5rem` (within a row), `1.25rem` (between
form fields), `2.5rem` (between sections), `4rem` (above page footer).
2. **One primary action per page.** Per screen, exactly one button uses the
solid `.fb-btn` (filled green). Everything else is `--secondary` or
`--ghost` or icon-only. Today most screens have 28 solid-or-near-solid
actions competing for attention.
3. **Smarter controls — collapse rows.** Anywhere we currently render 3+
buttons in a strip, the redesign keeps **one** primary inline (or zero —
"the row itself is the button") and tucks the rest behind a `⋯` menu
(`<details>` summary or a small popover). Status flips become pill
toggles instead of buttons. Destructive actions live *only* inside the
`⋯` menu, never as a top-level visible button.
4. **Visual hierarchy via type weight, not borders.** Inter is loaded — use
weight `700` for page-h1, `600` for section-h2, `500` for form labels,
`400` for body. Tracking `-0.02em` on headings (already in the CSS for
h1) extended to h2. This lets us drop a lot of decorative chrome.
5. **Optimistic UX.** Delete a row → row disappears immediately, with an
undo toast for ~6s. Toggle status → pill switches instantly, network
call in background. Errors revert the optimistic change and show a small
inline message. We already have Svelte 5 `$state` everywhere, so this
is plumbing, not architecture.
6. **No inline `style="..."` for layout.** Every inline style currently in
the .svelte files moves to a class in `feedback.css`. Two reasons: dark
mode lives in `@media (prefers-color-scheme: dark)` rules and inline
styles bypass it; and inline styles defeat the spacing-scale rule (1).
Optional principle 7 (suggest, but waiting for m): **list, not cards.** A
naked padded list with hover-revealed actions beats card-grids for a small N
(≈ <50 forms). Keeps the page feeling like *content*, not a dashboard.
---
## 3. Per-screen redesigns
### 3.1 `/` (landing)
```
┌────────────────────────────────────────┐
│ │
│ │
│ fdbck │ ← 2.5rem, weight 700, tracked -0.03em
│ feedback by link │ ← muted, 1rem, weight 400
│ │
│ │
│ [ Admin sign-in → ] │ ← single ghost button, sized fb-btn--lg
│ │
└────────────────────────────────────────┘
↑ massive vertical centering
```
- Centre the page vertically (max-width 480px, `min-height: 100vh`,
`display: grid; place-items: center;`).
- Drop the "This page is only reachable through a private link…" sentence
if a participant lands here they're not lost; the wordmark + sign-in is
enough.
- Wordmark grows to `2.5rem`, weight `700`, tracking `-0.03em`. Subtitle
shrinks to `1rem` muted.
- Single CTA, `fb-btn--lg fb-btn--ghost` with the existing `arrow-right`
icon (already used on login submit).
### 3.2 `/login`
```
┌────────────────────────────────────────┐
│ │
│ Sign in │ ← drop "Admin access only"
│ │
│ Email │
│ [______________________] │
│ │
│ Password │
│ [______________________] │
│ │
│ ⓘ inline error appears here, muted │
│ │
│ [ Sign in → ] │
└────────────────────────────────────────┘
```
- Drop the "Admin access only." subtitle (the URL says it).
- Vertical-centre the form (same grid trick as landing).
- Inline error: render as a small muted line *below* the submit button
rather than an `fb-banner--error` block above it. Less alarming, no
layout shift.
- Keep the existing primary `fb-btn` with arrow-right icon.
### 3.3 `/admin/feedback` (list) — **the biggest change**
```
┌────────────────────────────────────────────────────────────────────┐
│ Forms [ + New ] │ ← terse h1, primary CTA
│ ───────── │
│ │
│ My session feedback ●open ⋯ │ ← row hover-reveals ⋯
│ Form + chat · 12 responses · 7 messages │
│ │
│ ┌── 2.5rem of pure whitespace ──┐ │
│ │
│ Sprint 4 retro ○closed ⋯ │
│ Form · 0 responses │
│ │
│ ┌── 2.5rem of pure whitespace ──┐ │
│ │
│ Quick chat ●open ⋯ │
│ Chat · 21 messages │
└────────────────────────────────────────────────────────────────────┘
```
**Row anatomy:**
- The whole row title is a link goes to detail (today's "Edit" button
becomes implicit).
- Subtitle: mode + counts only. **Drop** the raw `/f/<slug>` line, the
`created DATE` ("created" word), and the mode pill fold mode into the
subtitle text ("Form + chat · 12 responses").
- Right side: a status dot+label (●open / closed) that *is the toggle*
click flips it (optimistic). One control replaces today's
pill-+-Close-button pair.
- Trailing `⋯` menu (`<details>` summary or popover) opens:
- Copy link
- Open
- Edit (explicit jump, even though row is also a link)
- ──────
- Delete (red)
- Drop `border + shadow + bg` on the row container. Rely on row-padding
+ `2.5rem` gap between rows. Hover state: faint `--color-bg-tertiary`
background, no border.
- Mobile (`< 640px`): keep the `⋯` always visible; on desktop reveal on
hover for a calmer default state.
**Header:**
- Drop the descriptive paragraph ("Collect feedback through forms…"). The
user already knows what fdbck is.
- H1 reads "Forms" (terser than "Feedback forms", since we're already at
`/admin/feedback`).
- Drop the H2 "Your forms (N)" the count moves into the H1 area as a
small muted number, or drops entirely (the rows themselves are the
count).
- Keep one solid `+ New` button on the right.
**Empty state:** generous whitespace + "No forms yet create your first
one." + the same `+ New` button as primary CTA.
**Optimistic delete:** after confirming, row disappears immediately;
toast at the bottom: "Form deleted. [Undo]" for 6s.
### 3.4 `/admin/feedback/new`
```
┌────────────────────────────────────────────────────────────────────┐
│ ← Forms │ ← terse back-link, no chip
│ │
│ New form │
│ │
│ Title │
│ [______________________________________________] │
│ │
│ Description (optional) │
│ [______________________________________________] │
│ │
│ ☐ Enable live chat │
│ │
│ ▸ Add questions now (advanced) │ ← collapsed by default
│ │
│ [ ✓ Create form ] │
└────────────────────────────────────────────────────────────────────┘
```
- Title + Description + chat checkbox are the *common path*. They occupy
the full page width without any JSON noise.
- The JSON textarea moves behind a `<details>` disclosure labelled "Add
questions now (advanced)". Inside the disclosure we keep:
- the `Insert sample` button (now sits *inside* the disclosure, where it
belongs)
- the textarea
- the helper paragraph
- Rationale: the visual builder on the detail page is the canonical path
for adding questions; offering JSON paste at *creation* is power-user
speed-up, not the default. By collapsing it, the new-form page reads
like 4 inputs and a button.
- Replace the back-link button with a plain `← Forms` text-link in muted
weight 500, no chip styling.
- Drop the page subtitle ("Set up a feedback form…"). The label "New form"
+ the form below carry the meaning.
- Move the chat toggle from a faux-`fb-option-row` checkbox to a proper
`.fb-toggle` with a clean label-on-the-left layout (new class small
CSS addition).
### 3.5 `/admin/feedback/[id]` (detail) — **the second-biggest change**
```
┌────────────────────────────────────────────────────────────────────────┐
│ ← Forms │
│ │
│ My session feedback ●open ⋯ │ ← title + clickable status pill + ⋯
│ Some optional description shown if present. │
│ │
│ msbls.de/vote [ Copy ] [ Open ↗ ] [ Replace ] │ ← share-link strip, INLINE in header
│ │
│ ───────────────────────────────────────────────────────────────── │ ← whitespace, no border
│ │
│ [ Chat (3) ] [ Results (12) ] [ Responses (12) ] [ Edit ] │
│ │
│ …active tab body, with 2.5rem top-padding… │
└────────────────────────────────────────────────────────────────────────┘
```
**Header collapse — 8 controls → 3 visible:**
| today's control | redesign |
| ------------------------------------ | ---------------------- |
| status pill (display only) | status pill, clickable to toggle (optimistic) |
| `/f/slug` raw text | dropped (the share strip below has the link) |
| Copy link button | inside share strip |
| Preview button | inside share strip ("Open ↗") |
| Close / Reopen button | merged into status pill |
| CSV button | inside `⋯` menu |
| JSON button | inside `⋯` menu |
| Delete button | inside `⋯` menu (red, last) |
`⋯` menu contents (in order, with separators):
1. Copy link (when the share strip is hidden on mobile)
2. Export CSV
3. Export JSON
4. ──────
5. Delete (red)
**Share section disappears as a separate block.** The short URL is shown
inline in the header as one strip:
- If `inst.short_url` exists: show it + Copy + Open + Replace (Replace
opens a small inline form *under* the strip same `<details>` pattern
as today, but compact).
- If it doesn't: show "No short link · [ Create one ]" click reveals
the slug input + create button.
This kills today's awkward "section between header and tabs" structure
and folds share into the place where the user expects "where do I share
this".
**Tabs unchanged in count and labels.** They stay: Chat / Results /
Responses / Edit. Selection style stays the segmented-pill (`fb-tabs` /
`fb-tab--active`). Whitespace between tab strip and tab body grows from
`1.25rem` to `2.5rem` so the tab body breathes.
**Edit tab inline polish:**
- Drop the duplicate `<h2>Edit · v3</h2>` heading inside the tab the
active tab pill already says "Edit". Save the version pill for a quiet
spot next to the Save button.
- The `Visual` / `JSON` toggle becomes a small segmented control in the
same shape as the tab pills (consistency).
- Save button is the page's primary action *while* this tab is active.
No other solid button on the page in that state.
**Banner about responses-already-received** (`{submissions.length}
responses already received…`) becomes a single muted line above the form,
not a banner box.
### 3.6 `/f/[slug]` (participant)
```
┌──────────────────────────────────────────┐
│ │
│ Title │ ← h1, room above
│ Optional description │
│ │
│ ⓘ closed (only if closed, neutral) │ ← muted not yellow when closed
│ │
│ ───────────────────────────────────── │ ← 3rem gap
│ │
│ Live-Feedback │
│ ┌── chat list ──────────────────────┐ │
│ │ … │ │
│ └───────────────────────────────────┘ │
│ [ textarea (full width) ] │
│ [Senden]│
│ │
│ ───────────────────────────────────── │ ← 3rem gap (same as above)
│ │
│ Fragebogen │
│ q1 │
│ q2 │
│ │
│ [ Absenden ] │
│ │
│ │
│ fdbck.msbls.de │
└──────────────────────────────────────────┘
```
- **Drop the inline-label name row.** Replace with a normal labelled field
matching the rest of the form:
```
Dein Name (optional)
[Anonym__________________________]
```
Or move it *below* the chat/form sections as a footer-style "Du
schreibst als: Anonym ✎" with click-to-edit. (Suggested — see open
question #5.) For v1 keep it at top but normalise its layout.
- Increase section gap from `1.75rem` to `3rem` between the chat block
and the form block, so they read as two distinct activities.
- Closed banner: switch from amber `--color-warning` palette to a quiet
neutral muted style (1px top border + small italic line) — closed is a
state, not an alert.
- Drop the `border-color: var(--color-primary)` on `.fb-chat__post--mine`
in favour of a subtle left-border-only accent (3px, `--color-primary`).
The current full pill-with-coloured-border treatment is loud.
- Footer `fdbck.msbls.de` → wrap as a permalink to `/`, very muted.
---
## 4. Implementation plan
The redesign is *only* CSS + small `.svelte` markup edits. No new
components, no new dependencies, no schema changes. Suggested commit order
(each commit is independently mergeable and testable):
### Commit 1 — CSS foundation: spacing scale + typography rhythm
- `src/lib/styles/feedback.css`:
- Add a spacing scale as CSS custom properties (`--space-1` through
`--space-7`, or named `--gap-row / --gap-field / --gap-section /
--gap-foot`).
- Bump `.fb-section` margin-bottom from `1.75rem` → `--gap-section`
(≈ `2.5rem`).
- `.fb-header h1` weight stays 700; `.fb-section h2` weight bumps from
`600` → `600` (no change) but tracking `-0.01em` already there.
- Add `.fb-page-narrow` (max-width `480px`) and `.fb-page-center`
(vertical grid centre) modifiers for landing/login.
- Add `.fb-toggle` for label-left+switch-right boolean fields.
- Add `.fb-row` for spacious list rows (no border, no shadow, hover
bg) plus `.fb-row__title`, `.fb-row__meta`, `.fb-row__actions`.
- Add `.fb-status-pill` (clickable open/closed pill).
- Add `.fb-menu` (the `` dropdown — implemented as `<details>` +
`<summary>` + a positioned panel).
- Add `.fb-share-strip` (the inline header share row in 3.5).
- No structural Svelte changes in this commit — verify in the browser
that the existing pages still render fine since added classes are
unused additions.
### Commit 2 — landing + login (cheap wins)
- `src/routes/+page.svelte`: drop the second paragraph; wrap shell in
`fb-page-center fb-page-narrow`; bump wordmark size.
- `src/routes/login/+page.svelte`: drop the "Admin access only."
subtitle; wrap in `fb-page-center fb-page-narrow`; move error from
`fb-banner--error` block to a small inline muted line.
- Verify both routes in the browser at 375px / 1024px / 1440px.
### Commit 3 — `/admin/feedback/new`
- `src/routes/admin/feedback/new/+page.svelte`:
- Drop the page subtitle.
- Replace the chat-checkbox block with `.fb-toggle`.
- Wrap "Questions (JSON, optional)" + sample button + textarea +
helper inside a `<details>` with summary "Add questions now
(advanced)".
- Remove inline `style="..."` on the back-link block; replace with a
`.fb-back-link` class (text-only, muted).
### Commit 4 — `/admin/feedback` (list) — biggest change, isolated commit
- `src/routes/admin/feedback/+page.svelte`:
- Drop the H1 paragraph.
- Drop the H2 "Your forms (N)".
- Replace each row (today's bordered card with 5 buttons) with the
`.fb-row` pattern from commit 1: title is a link to detail,
subtitle merges mode + counts, right side is `.fb-status-pill`
(toggle) + `.fb-menu` trigger.
- Move all inline `style="..."` to classes (no new feature).
- Add the `` menu component inline using `<details>` — no JS
framework needed; click-outside-to-close via a small `addEventListener`
in `onMount`.
- Add optimistic delete with undo toast (small `<aside>` element fixed
to bottom-centre, `setTimeout` 6s, calls `DELETE` only after timeout
expires).
- Verify the live deployed list still looks right after deploy.
### Commit 5 — `/admin/feedback/[id]` (detail) — second-biggest change
- `src/routes/admin/feedback/[id]/+page.svelte`:
- Header collapse per 3.5: status becomes `.fb-status-pill`, drop
raw `/f/slug` text, drop inline Copy/Preview/Close/Reopen/CSV/
JSON/Delete buttons.
- Add `.fb-share-strip` directly under the title/description in the
header (replaces the standalone Share section below).
- Add `.fb-menu` with Copy link / Export CSV / Export JSON /
────── / Delete.
- Delete the standalone `<section data-fb-share>` block — its
contents are now in the header strip + a "Replace" inline form.
- Inside Edit tab: drop the `<h2>Edit · v3</h2>`, move version pill
next to Save; turn Visual/JSON into a segmented pill control
matching `.fb-tabs`.
- Move `submissions.length` warning from `.fb-banner` to muted line.
- Replace inline `style="..."` with classes throughout.
### Commit 6 — `/f/[slug]` participant polish
- `src/routes/f/[slug]/+page.svelte`:
- Replace the inline-label name row with a stacked-label field.
- Increase gap between Chat and Form sections (use `--gap-section`).
- Switch "(closed)" banner to neutral muted style (a new
`.fb-status-line--muted` modifier on `.fb-banner` or a dedicated
`.fb-closed-line` class).
- Adjust `.fb-chat__post--mine` styling: drop full coloured border,
add `border-left: 3px solid var(--color-primary)` only.
- Wrap footer text in an `<a href="/">` with `aria-label="fdbck home"`.
### Commit 7 — sweep: optimistic toggles, hover-reveal actions
- Add the optimistic-update + undo-toast pattern to `setStatus` on the
detail page (status pill instant flip, server call after).
- Apply the same to per-row `toggleStatus` on the list page.
- Verify dark-mode pass: walk all five routes in dark mode (browser
emulator) since multiple inline `style="..."` strings were converted
to classes that inherit from `:root` / `prefers-color-scheme`.
---
## 5. Open questions for m
These are decisions m should weigh in on before implementation. Each has
my recommendation, but they're all reversible.
1. **Cards vs spacious list for `/admin/feedback`.** I'm proposing a
spacious list (no border, lots of whitespace, hover-revealed ``).
The brief mentions cards as an option. **My recommendation: list.**
Cards add visual chrome (border + shadow) which is the opposite of
"negative space". Cards earn their keep when each item has rich
content (image, multi-line preview); fdbck rows have title + 2
meta lines.
2. **Optimistic delete with 6s undo, or keep the `confirm()` modal?**
Today both list and detail use `confirm("…cannot be undone")`. The
undo toast is smoother but trades safety for fluency. **My
recommendation: undo toast** — the row reappears identically if
undone, the destructive call only fires after timeout, no data is
actually at risk during the 6s window. Keep `confirm()` only on
detail-page Delete (deleting from the detail page is a more
deliberate action and merits an extra step).
3. **Share-link strip in the detail header — does it belong there?**
I'm folding the standalone Share section *into* the header (3.5).
Alternative: keep Share as a section but move it *below* the tabs,
so the header stays minimal. **My recommendation: in the header.**
Sharing the link is the second-most-common action after viewing
results; it belongs near the title.
4. **Drop the Edit tab body's inner H2?** Today every tab body has an
`<h2>` echoing the tab name (`<h2>Live chat</h2>`,
`<h2>Results</h2>`, etc.). I want to drop these — the tab strip
already labels the active section. But this is a stylistic call.
**My recommendation: drop the inner H2s,** add `2rem` of top
padding to the tab body so the active tab pill alone titles the
section.
5. **Participant name field — top, bottom-as-footer, or bottom-as-
"edit"?** Today it's at the top with an inline label. I'm proposing
stacking it the same as other fields. A bolder alternative: move
it to a footer-style "Du schreibst als: Anonym ✎" below all
sections. **My recommendation for v1: stacked label, top.** Bolder
move waits for v2.
6. **Locale homogenisation.** Admin pages are English, participant
page is German. Out of scope for this redesign — flagging only so
we don't accidentally translate one of them while doing the markup
pass. Confirm this stays as-is.
7. **Accent on `--color-primary`.** Same green stays per brief. But
today some screens have `box-shadow: 0 0 0 3px rgb(22 163 74 /
0.15)` on focus and others have `0.25` opacity — minor inconsistency.
Worth normalising during commit 1? **My recommendation: yes,
normalise to one focus-ring rule (0.2 opacity, 3px).**
---
## 6. Anti-scope (explicitly NOT in this redesign)
- Palette: no new colours, no new accent.
- Stack: still SvelteKit + vanilla CSS + Inter. No new deps.
- Routes: unchanged URL structure.
- Data model: unchanged.
- Locale: no homogenisation (see Q6).
- Polling intervals (5s admin, 3s chat): unchanged.
- Auth flow / share-link backend: unchanged (only the *display* of the
share link in the detail header changes).