Settle on one visual language

The interface had drifted into two of everything. The calendar and its
popovers were built around a blue accent the rest of the app had long since
replaced with green, five different sizes served the same class of small
label, and page sections were a stack of identical bordered cards that gave
no sense of what mattered most. Sections now separate by space and a hairline,
the overview leads with its headline figure at a size that says so, and the
palette, type scale and spacing live in one place as variables rather than
scattered literals.

Two things were not styled at all. The sign-in screen was an unstyled form in
the top-left corner, and the tip cards had no rules whatsoever despite their
markup already carrying a severity, so every tip rendered identically with a
plain green square for its dismiss control.

The calendar was also unusable on a narrow screen: the preset rail never
collapsed and covered the last three columns of the grid.
This commit is contained in:
2026-09-18 01:39:34 +02:00
parent f2b3920cbc
commit 296b596778
15 changed files with 757 additions and 433 deletions
+52 -6
View File
@@ -3,7 +3,16 @@
@import './modals.css';
@import './responsive.css';
/* Design Tokens */
/* Design Tokens
*
* One neutral ground + one accent; every other colour is semantic (danger/
* warning/success) and exists as a solid + "-weak" tint pair. Everything
* below is used app-wide, including the calendar and modal families that
* used to hardcode their own hex values — see calendar.css/period-popover.css/
* etc. Two values are load-bearing for e2e: --c-danger-weak (red day
* background) and --c-weekend-bg (plain-Saturday background) — read
* directly by frontend/e2e/tests/red-days.spec.ts. Do not repurpose either.
*/
:root {
/* Color - calm, trustworthy palette */
--c-bg: #f7f8fa;
@@ -11,13 +20,37 @@
--c-border: #e3e6eb;
--c-text: #1c2733;
--c-text-muted: #5b6675;
--c-accent: #2f6f4f; /* calm green */
--c-text-faint: #94a0ac;
--c-accent: #2f6f4f; /* calm green — the app's one accent */
--c-accent-weak: #e8f1ec;
--c-accent-hover: #1f5a3b;
--c-accent-active: #0f4a2f;
--c-danger: #b3261e;
--c-danger-weak: #fdeceb;
--c-danger-weak: #fdeceb; /* also the red-day cell background — see note above */
--c-danger-hover: #8a1a15;
--c-success: #1e7d4f;
--c-success-weak: #e7f4ec;
--c-success-hover: #0d6a37;
--c-warning: #8a6d1f;
--c-warning-weak: #fef8e7;
/* Calendar-specific semantics (klämdag/weekend/red-day borders + hover) —
* kept distinct from the generic danger/warning pair above because a red
* day and a klämdag are both visible on screen at once and need to read
* as different hues, not different intensities of the same one. */
--c-weekend-bg: #f0f0f0; /* plain Saturday — read directly by red-days.spec.ts */
--c-weekend-border: #cfcfcf;
--c-weekend-hover: #e8e8e8;
--c-redday-border: #d9776e;
--c-redday-hover: #fbdedb;
--c-klamdag-bg: #fef8e7;
--c-klamdag-border: #d9b23c;
--c-klamdag-hover: #fcf0c8;
/* The one deliberately loud color in the app — a "this just changed"
* flash ring on a calendar band, never a static/resting state. */
--c-flash: #ffd54f;
--overlay: rgba(16, 24, 40, 0.5);
/* Spacing scale (8px base) */
--sp-1: 4px;
@@ -29,6 +62,8 @@
--sp-8: 48px;
/* Type scale */
--fs-2xs: 0.6875rem;
--fs-xs: 0.75rem;
--fs-sm: 0.875rem;
--fs-base: 1rem;
--fs-lg: 1.25rem;
@@ -37,7 +72,13 @@
--lh: 1.5;
/* Shape & depth */
--radius-sm: 6px;
--radius: 8px;
--radius-full: 999px;
/* Matches frontend/e2e/tests/calendar-band.spec.ts's literal 4px/0px
* assertions on band corners — kept as its own token (not tied to
* --radius-sm) so a future radius change there can't silently break it. */
--radius-band: 4px;
--shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
--shadow-md: 0 4px 12px rgba(16, 24, 40, 0.08);
@@ -148,22 +189,27 @@ body {
font-size: var(--fs-base);
}
/* Headings */
/* Headings — tighter leading than body text, the usual editorial cue that a
* line is a heading rather than another sentence of the paragraph below it. */
h1 {
font-size: var(--fs-2xl);
font-weight: 700;
line-height: 1.2;
letter-spacing: -0.01em;
margin-bottom: var(--sp-4);
}
h2 {
font-size: var(--fs-xl);
font-weight: 700;
line-height: 1.25;
margin-bottom: var(--sp-3);
}
h3 {
font-size: var(--fs-lg);
font-weight: 600;
line-height: 1.3;
margin-bottom: var(--sp-3);
}
@@ -250,7 +296,7 @@ textarea:focus {
input:disabled,
select:disabled,
textarea:disabled {
background-color: #f0f0f0;
background-color: var(--c-bg);
cursor: not-allowed;
}
@@ -323,7 +369,7 @@ main {
.warning-message {
padding: var(--sp-3) var(--sp-4);
background-color: #fef8e7;
background-color: var(--c-warning-weak);
color: var(--c-warning);
border-left: 4px solid var(--c-warning);
border-radius: var(--radius);