Redesign the setup flow and consolidate the CSS into one primitives layer

Onboarding asks explicitly for one or two parents and shows one card per
parent for balances; the balance form is per parent with inline
validation; the partner can be filled from the FK deduction or added
from it. Settings and Dashboard reuse the same form.

CSS: bare buttons carry no colour any more; buttons, cards, choice
cards, fields, alerts, badges, eyebrow and modal chrome are defined once
in primitives.css. Media queries live only in responsive.css. A style
guard test blocks hex, !important and stray media queries. Bilingual
fixes: calendar selects size by content, header no longer wraps. Vitest
is capped at four workers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-19 12:27:29 +02:00
parent e4719cb9ae
commit ae6db7e16f
105 changed files with 5683 additions and 3690 deletions
@@ -84,7 +84,7 @@ export function DayOverridesInput({
type="button"
onClick={() => handleRemove(override.id)}
disabled={isSubmitting || isLoading}
className="day-overrides-input__remove-button"
className="btn btn--danger btn--sm btn--block"
data-testid={`remove-override-${override.id}`}
>
{t('common.delete')}
@@ -98,8 +98,10 @@ export function DayOverridesInput({
<form onSubmit={handleAddOverride} className="day-overrides-input__form" data-testid="add-override-form">
<h3>{t('dayOverridesInput.addSectionTitle')}</h3>
<div className="day-overrides-input__form-group">
<label htmlFor="override-date">{t('dayOverridesInput.dateLabel')}</label>
<div className="field day-overrides-input__form-group">
<label htmlFor="override-date" className="field__label">
{t('dayOverridesInput.dateLabel')}
</label>
<input
id="override-date"
type="date"
@@ -108,7 +110,7 @@ export function DayOverridesInput({
required
disabled={isSubmitting || isLoading}
data-testid="override-date-input"
className="day-overrides-input__form-input"
className="field__control"
/>
</div>
@@ -142,8 +144,10 @@ export function DayOverridesInput({
</fieldset>
</div>
<div className="day-overrides-input__form-group">
<label htmlFor="override-note">{t('dayOverridesInput.noteFieldLabel')}</label>
<div className="field day-overrides-input__form-group">
<label htmlFor="override-note" className="field__label">
{t('dayOverridesInput.noteFieldLabel')}
</label>
<input
id="override-note"
type="text"
@@ -153,7 +157,7 @@ export function DayOverridesInput({
maxLength={280}
disabled={isSubmitting || isLoading}
data-testid="override-note-input"
className="day-overrides-input__form-input"
className="field__control"
/>
<small className="day-overrides-input__char-count">
{t('dayOverridesInput.charCount', { count: note.length })}
@@ -163,7 +167,7 @@ export function DayOverridesInput({
<button
type="submit"
disabled={isSubmitting || isLoading || !date}
className="day-overrides-input__submit-button"
className="btn btn--primary btn--block"
data-testid="add-override-button"
>
{isSubmitting ? t('dayOverridesInput.addingButton') : t('dayOverridesInput.addButton')}