80b4f1cb52
The dashboard now leads with a typographic headline, three key figures, per-parent age-4 bars and one row per year until the fourth birthday. Each year row shows the timeline bands beside each parent's parental-leave days left at year end and vacation days left, carried over or expiring, and opens into a per-parent table with that year's wish outcomes. Tips become a plain list and absorb the planner's surplus advice; "Detaljer" keeps the metrics and a balance snapshot for every parent. The separate plan-proposal fold and the type-count table are gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBRLomdLK9jF7wU7a8AA6H
451 lines
9.7 KiB
CSS
451 lines
9.7 KiB
CSS
/* Component styles - must come first */
|
||
@import './primitives.css';
|
||
@import './components.css';
|
||
@import './responsive.css';
|
||
|
||
/* Typeface — Schibsted Grotesk (OFL), self-hosted from /public/fonts so no
|
||
* request ever leaves for a font CDN. Two subsets with Google's own
|
||
* unicode-ranges: the browser only fetches latin-ext when a glyph needs it.
|
||
* Variable weight axis 400–900; `swap` so text is never invisible while the
|
||
* file loads (index.html preloads the latin file to keep that swap short). */
|
||
@font-face {
|
||
font-family: 'Schibsted Grotesk';
|
||
font-style: normal;
|
||
font-weight: 400 900;
|
||
font-display: swap;
|
||
src: url('/fonts/SchibstedGrotesk-latin-ext-v7.woff2') format('woff2');
|
||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
|
||
U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
|
||
U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||
}
|
||
|
||
@font-face {
|
||
font-family: 'Schibsted Grotesk';
|
||
font-style: normal;
|
||
font-weight: 400 900;
|
||
font-display: swap;
|
||
src: url('/fonts/SchibstedGrotesk-latin-v7.woff2') format('woff2');
|
||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
|
||
U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||
}
|
||
|
||
/* Design Tokens
|
||
*
|
||
* One neutral ground, one accent. Hierarchy comes from type and whitespace;
|
||
* hairlines only where a boundary is unavoidable; one shadow, only on
|
||
* floating layers. Leave types are told apart by fill / ink / outline, not
|
||
* by hue, and day states by the numeral, not by a cell fill.
|
||
*
|
||
* Four names are load-bearing for e2e, which resolves them by name and
|
||
* compares against painted elements: --c-danger-weak (red-day cell),
|
||
* --c-weekend-bg (plain Saturday), --c-accent-hover and --c-surface
|
||
* (header-nav-hover). Do not repurpose any of them.
|
||
*/
|
||
:root {
|
||
--font-sans: 'Schibsted Grotesk', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||
|
||
/* Neutrals */
|
||
--c-bg: #fcfcfd;
|
||
--c-surface: #fff;
|
||
--c-border: #ececf0;
|
||
--c-text: #111318;
|
||
--c-text-muted: #5e6472;
|
||
--c-text-faint: #9297a3;
|
||
|
||
/* The one accent — CTA, focus, active nav, today, selection */
|
||
--c-accent: #2f5bea;
|
||
--c-accent-weak: #eef2fe;
|
||
--c-accent-hover: #2549c4;
|
||
--c-accent-active: #1d3ca3;
|
||
|
||
/* Semantic */
|
||
--c-danger: #d03a2f;
|
||
--c-danger-weak: #fbeceb;
|
||
--c-danger-hover: #b02f26;
|
||
--c-warning: #b26a00;
|
||
--c-warning-weak: #fdf3e3;
|
||
--c-success: var(--c-accent);
|
||
--c-success-weak: var(--c-accent-weak);
|
||
--c-success-hover: var(--c-accent-hover);
|
||
|
||
/* Day states — a colour on the numeral, never a cell fill */
|
||
--c-day-red: var(--c-danger);
|
||
--c-day-klamdag: var(--c-warning);
|
||
--c-day-saturday: var(--c-text-faint);
|
||
--c-weekend-bg: var(--c-surface); /* legacy name; Saturday has no fill */
|
||
|
||
/* Leave types: fill / ink / outline */
|
||
--c-leave-vacation: #eef2fe;
|
||
--c-leave-vacation-ink: #2f5bea;
|
||
/* Stronger vacation step for thin (8px) timeline tracks only — the tint
|
||
* above vanishes on white at that height. Calendar bands keep the tint. */
|
||
--c-leave-vacation-bar: #b9c9f7;
|
||
--c-leave-sjukpenning: #2a2d35;
|
||
--c-leave-sjukpenning-ink: #fff;
|
||
--c-leave-lagsta: #fff;
|
||
--c-leave-lagsta-ink: #2a2d35;
|
||
--c-leave-lagsta-outline: #2a2d35;
|
||
--c-leave-lagsta-hatch: rgba(42, 45, 53, 0.35);
|
||
--c-band-gap: #f1f2f5;
|
||
--c-band-cap-self: var(--c-accent);
|
||
--c-band-cap-partner: #9297a3;
|
||
|
||
/* Interaction chrome */
|
||
--c-flash: var(--c-accent);
|
||
--overlay: rgba(17, 19, 24, 0.4);
|
||
--c-focus-ring: rgba(47, 91, 234, 0.35);
|
||
--c-row-hover: rgba(47, 91, 234, 0.04);
|
||
|
||
/* Spacing */
|
||
--sp-1: 4px;
|
||
--sp-2: 8px;
|
||
--sp-3: 12px;
|
||
--sp-4: 16px;
|
||
--sp-5: 24px;
|
||
--sp-6: 32px;
|
||
--sp-7: 48px;
|
||
--sp-8: 64px;
|
||
|
||
/* Type scale 12/14/16/20/28/40 — nothing below 12px anywhere */
|
||
--fs-xs: 0.75rem;
|
||
--fs-sm: 0.875rem;
|
||
--fs-base: 1rem;
|
||
--fs-lg: 1.25rem;
|
||
--fs-xl: 1.75rem;
|
||
--fs-2xl: 2.5rem;
|
||
--lh: 1.5;
|
||
--lh-tight: 1.15;
|
||
|
||
/* Shape & depth */
|
||
--radius-sm: 4px;
|
||
--radius: 8px;
|
||
--radius-lg: 12px;
|
||
--radius-full: 999px;
|
||
/* Matches frontend/e2e/tests/calendar-band.spec.ts's literal 4px/0px
|
||
* assertions on band corners — kept as its own token so a future radius
|
||
* change elsewhere can't silently break it. */
|
||
--radius-band: 4px;
|
||
--shadow-float: 0 8px 24px rgba(17, 19, 24, 0.1);
|
||
|
||
/* Sizes */
|
||
--maxw: 960px;
|
||
--control-h: 40px;
|
||
--control-h-sm: 32px;
|
||
--icon-sm: 16px;
|
||
--icon-md: 20px;
|
||
--icon-lg: 24px;
|
||
|
||
/* Layers */
|
||
--z-header: 100;
|
||
--z-popover: 900;
|
||
--z-modal: 1000;
|
||
|
||
/* The one inline image in the system: a 1.5px chevron for native selects.
|
||
* Lives here (not in a feature file) so the style guard can keep `url(`
|
||
* and hex out of everything else. Colour = --c-text-muted. */
|
||
--icon-chevron-down: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 8"><path d="M1 1l5 5 5-5" stroke="%235e6472" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>');
|
||
|
||
color-scheme: light;
|
||
}
|
||
|
||
/* Reset & Base */
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
html,
|
||
body,
|
||
div,
|
||
span,
|
||
iframe,
|
||
h1,
|
||
h2,
|
||
h3,
|
||
h4,
|
||
h5,
|
||
h6,
|
||
p,
|
||
blockquote,
|
||
pre,
|
||
a,
|
||
abbr,
|
||
address,
|
||
cite,
|
||
code,
|
||
del,
|
||
dfn,
|
||
em,
|
||
img,
|
||
ins,
|
||
kbd,
|
||
q,
|
||
s,
|
||
samp,
|
||
small,
|
||
strong,
|
||
sub,
|
||
sup,
|
||
b,
|
||
u,
|
||
i,
|
||
dl,
|
||
dt,
|
||
dd,
|
||
ol,
|
||
ul,
|
||
li,
|
||
fieldset,
|
||
form,
|
||
label,
|
||
legend,
|
||
table,
|
||
caption,
|
||
tbody,
|
||
tfoot,
|
||
thead,
|
||
tr,
|
||
th,
|
||
td,
|
||
article,
|
||
aside,
|
||
details,
|
||
figure,
|
||
figcaption,
|
||
footer,
|
||
header,
|
||
hgroup,
|
||
main,
|
||
mark,
|
||
nav,
|
||
output,
|
||
section,
|
||
summary,
|
||
time {
|
||
margin: 0;
|
||
padding: 0;
|
||
border: 0;
|
||
}
|
||
|
||
html {
|
||
-webkit-text-size-adjust: 100%;
|
||
text-size-adjust: 100%;
|
||
}
|
||
|
||
body {
|
||
font-family: var(--font-sans);
|
||
font-size: var(--fs-base);
|
||
line-height: var(--lh);
|
||
background: var(--c-bg);
|
||
color: var(--c-text);
|
||
-webkit-font-smoothing: antialiased;
|
||
text-rendering: optimizeLegibility;
|
||
}
|
||
|
||
/* Headings — tighter leading and a touch of negative tracking at 28px+ is
|
||
* what makes a line read as a heading, not a heavier weight. */
|
||
h1 {
|
||
font-size: var(--fs-xl);
|
||
font-weight: 600;
|
||
line-height: var(--lh-tight);
|
||
letter-spacing: -0.02em;
|
||
margin-bottom: var(--sp-4);
|
||
}
|
||
|
||
h2 {
|
||
font-size: var(--fs-lg);
|
||
font-weight: 600;
|
||
line-height: 1.25;
|
||
letter-spacing: -0.01em;
|
||
margin-bottom: var(--sp-3);
|
||
}
|
||
|
||
h3 {
|
||
font-size: var(--fs-base);
|
||
font-weight: 600;
|
||
line-height: 1.3;
|
||
margin-bottom: var(--sp-2);
|
||
}
|
||
|
||
/* Text */
|
||
p {
|
||
margin-bottom: var(--sp-3);
|
||
}
|
||
|
||
small {
|
||
font-size: var(--fs-sm);
|
||
color: var(--c-text-muted);
|
||
}
|
||
|
||
/* Lists */
|
||
ul,
|
||
ol {
|
||
margin-left: var(--sp-5);
|
||
margin-bottom: var(--sp-3);
|
||
}
|
||
|
||
li {
|
||
margin-bottom: var(--sp-2);
|
||
}
|
||
|
||
/* Links */
|
||
a {
|
||
color: var(--c-accent);
|
||
text-decoration: none;
|
||
}
|
||
|
||
a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
a:focus-visible {
|
||
outline: 2px solid var(--c-accent);
|
||
outline-offset: 2px;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
/* Buttons - base
|
||
*
|
||
* A plain reset only — no color, no padding beyond zero. Every visible
|
||
* button opts into a look via a `.btn` variant (see primitives.css) so a
|
||
* semantic element that happens to be a `<button>` (a card, a chip, a day
|
||
* cell) never inherits a color scheme it didn't ask for. */
|
||
button {
|
||
font: inherit;
|
||
color: inherit;
|
||
background: none;
|
||
border: 0;
|
||
padding: 0;
|
||
cursor: pointer;
|
||
border-radius: 0;
|
||
}
|
||
|
||
button:disabled {
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
/* Inputs & Selects
|
||
*
|
||
* Matches `.field__control` in primitives.css (hairline, 40px, 2px accent
|
||
* ring on focus) so an unclassed input still looks right. Checkboxes and
|
||
* radios are excluded — they keep their native intrinsic size and just pick
|
||
* up the accent color. */
|
||
input:not([type='checkbox']):not([type='radio']),
|
||
select,
|
||
textarea {
|
||
width: 100%;
|
||
min-height: var(--control-h);
|
||
font-family: inherit;
|
||
font-size: var(--fs-base);
|
||
line-height: 1.25;
|
||
border: 1px solid var(--c-border);
|
||
border-radius: var(--radius);
|
||
padding: var(--sp-2) var(--sp-3);
|
||
background: var(--c-surface);
|
||
color: var(--c-text);
|
||
transition: border-color 0.15s, box-shadow 0.15s;
|
||
}
|
||
|
||
select {
|
||
appearance: none;
|
||
padding-right: var(--sp-6);
|
||
background-image: var(--icon-chevron-down);
|
||
background-repeat: no-repeat;
|
||
background-position: right var(--sp-3) center;
|
||
background-size: 12px 8px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
input:focus,
|
||
select:focus,
|
||
textarea:focus {
|
||
outline: none;
|
||
border-color: var(--c-accent);
|
||
box-shadow: 0 0 0 2px var(--c-accent);
|
||
}
|
||
|
||
input:focus-visible,
|
||
select:focus-visible,
|
||
textarea:focus-visible {
|
||
outline: none;
|
||
}
|
||
|
||
input:disabled,
|
||
select:disabled,
|
||
textarea:disabled {
|
||
background-color: var(--c-bg);
|
||
color: var(--c-text-muted);
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
input::placeholder,
|
||
textarea::placeholder {
|
||
color: var(--c-text-faint);
|
||
}
|
||
|
||
input[type='checkbox'],
|
||
input[type='radio'] {
|
||
width: auto;
|
||
accent-color: var(--c-accent);
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* Number inputs — hide the native up/down spinner everywhere. Callers still
|
||
* get numeric-only mobile keyboards via `inputmode="numeric"`. */
|
||
input[type='number'] {
|
||
appearance: textfield;
|
||
}
|
||
|
||
input[type='number']::-webkit-outer-spin-button,
|
||
input[type='number']::-webkit-inner-spin-button {
|
||
appearance: none;
|
||
margin: 0;
|
||
}
|
||
|
||
input[type='date']::-webkit-calendar-picker-indicator {
|
||
opacity: 0.6;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* Label */
|
||
label {
|
||
display: block;
|
||
margin-bottom: var(--sp-2);
|
||
font-weight: 500;
|
||
color: var(--c-text);
|
||
}
|
||
|
||
/* Tables — no header fill; one hairline per row. */
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
}
|
||
|
||
th {
|
||
text-align: left;
|
||
font-weight: 500;
|
||
font-size: var(--fs-sm);
|
||
padding: var(--sp-2) var(--sp-3);
|
||
border-bottom: 1px solid var(--c-border);
|
||
color: var(--c-text-muted);
|
||
}
|
||
|
||
td {
|
||
padding: var(--sp-3) var(--sp-3);
|
||
border-bottom: 1px solid var(--c-border);
|
||
}
|
||
|
||
tr:hover td {
|
||
background-color: var(--c-row-hover);
|
||
}
|
||
|
||
/* Utility classes for form */
|
||
.form-group {
|
||
margin-bottom: var(--sp-5);
|
||
}
|
||
|
||
.form-group label {
|
||
margin-bottom: var(--sp-2);
|
||
}
|