Design System Governance
A consolidation audit and governance framework for the Samtrygg design system. Not a redesign proposal — a steering document.
1. Executive Summary
The Samtrygg design system has a strong foundation: a coherent brand palette built around #FF6D59, a distinctive proprietary typeface (Nuckle), a well-structured 8px spacing scale, and a component language that is largely consistent in intent if not in implementation. The Design System document is intended to be the single source of truth and is mostly correct, but the current page implementations do not yet reflect it consistently.
However, an audit of 38 pages reveals three structural problems that will compound as the product grows:
The :root defines 10 primitive colour tokens. Pages use 40–60 raw hex values that are not mapped to any token. Feedback colours (#1a7a3c, #8b5a00, #e7f5ed, #fdecea) appear on nearly every page with no token name. When these colours need to change, every usage must be hunted manually across all files.
The Design System defines btn--primary (BEM). Pages use btn-primary (single dash). These are two parallel, incompatible systems operating simultaneously. The DS wins on paper; the pages win in practice. Neither is authoritative.
--sam-red is used for CTAs, error borders, and decorative brand accents simultaneously. There is no semantic mapping between primitive values and their intended function. When the brand evolves, the intent is invisible to anyone reading the code.
These are fixable without a rebuild. The system is not broken — it is incomplete. The recommendations in this document are conservative, prioritised, and practical.
2. Design Principles
These six principles should guide every future design system decision. They are not aesthetic preferences — they are decision filters. When a proposed change conflicts with one of these principles, the principle wins unless there is a strong, documented reason to override it.
Warm, not soft
Samtrygg handles one of the most significant financial relationships a person has. The design should feel warm and human, but never vague or imprecise. Clarity is a form of care. Do not sacrifice legibility or structure in pursuit of warmth.
Trust through consistency
Inconsistency erodes trust faster than any single bad design decision. Every component should behave the same way in every context. A button that looks different on page 12 than it does on page 3 signals unreliability — even to users who cannot name what they noticed.
One source of truth
If a value, colour, or pattern is defined in the design system, it must not be redefined locally. Local exceptions are technical debt dressed as pragmatism. The system is only as useful as it is complete and enforced.
Functional before decorative
Every visual element should serve a communicative function. Decorative colour, unnecessary shadows, and gratuitous animation dilute the signal-to-noise ratio. If removing an element does not change what the user understands, remove it.
Brand has a context
Brand expressiveness belongs on public-facing surfaces. Product surfaces — account pages, forms, dashboards — should recede and let the task take precedence. The same brand DNA applies to both, but the emphasis is different. Do not bring marketing energy into a lease agreement form.
Design for implementation
A design decision that cannot be implemented consistently across the codebase is not a design decision — it is a wish. Every pattern added to the system must come with a clear token, class, or component name. Ambiguous naming is a bug.
Exceptions are allowed only when they are documented and intentionally reusable. A local exception that solves only one page is usually a missing token, variant, or component — not a legitimate exception. Treat it as a signal to extend the system, not to bypass it.
3. What to Keep
| Element | Reason |
|---|---|
Core palette--sam-red: #FF6D59, --sam-dark: #313131, --sam-brown-* family | Distinctive, warm, proprietary. The warm-brown neutrals in particular are a genuine differentiator from the grey-dominant rental market. Do not swap or extend the palette without strong reason. |
8px spacing scale--s-1 through --s-9 | Correct base, well-distributed steps. Covers all practical layout needs without gaps or redundancy. |
Radius system--radius-sm through --radius-pill | Consistent and already used correctly across pages. The pill radius on buttons is a recognisable brand mark. |
| Three-level shadow system | Well-calibrated. Shadow-1 for resting state, shadow-2 for hover lift, shadow-3 for modals and overlays. Not overdone. |
| Nuckle as primary typeface | Strong brand differentiator. Works at both display and body sizes. Manrope as fallback is the right choice — compatible rhythm, similar proportions. |
Button base with CSS custom property injection--btn-bg, --btn-fg, --btn-border | Excellent pattern. Variants are created by overriding local properties, not by repeating the full rule set. Keep and extend. |
| Handoff bar convention | The dark bar on every mockup page encoding route, controller, and field names is a practical developer communication tool. Preserve this pattern as mockups evolve. |
4. What to Change
4a. Add a semantic colour layer
The current system is primitive only. Every colour decision requires knowing the brand palette by heart. A thin semantic layer adds intent without changing any visual output:
/* Interactive */ --color-action: var(--sam-red); --color-action-hover: color-mix(in oklab, var(--sam-red) 88%, black); --color-action-fg: var(--sam-white); /* Feedback */ --color-success: #1a7a3c; /* currently raw hex on 30+ pages */ --color-success-bg: #e7f5ed; --color-warning: #8b5a00; --color-warning-bg: #fff4e0; --color-danger: var(--sam-error); --color-danger-bg: #fdecea; --color-info: #1a4a8a; --color-info-bg: #e8f0fe; /* Surface */ --surface-base: var(--sam-brown-light); /* page background */ --surface-raised: var(--sam-white); /* cards */ --surface-sunken: #f7f8fc; /* inputs, OTP, code blocks */ --surface-overlay: rgba(49,49,49,.50); /* modal backdrops */ --surface-inverse: var(--sam-dark); /* dark sections, topband, footer */ /* Text */ --text-primary: var(--sam-dark); --text-secondary: var(--sam-medium); --text-disabled: var(--sam-light); --text-inverse: var(--sam-white); --text-link: var(--sam-red); /* Border */ --border-default: var(--sam-light); --border-strong: var(--sam-dark); --border-focus: var(--sam-dark); --border-error: var(--sam-error);
4b. Unify the button class system
Two incompatible button systems currently co-exist:
| Design System (BEM) | Pages (single dash) | Resolution |
|---|---|---|
btn--primary | btn-primary | Adopt BEM throughout |
btn--secondary | btn-secondary | Adopt BEM throughout |
btn--ghost | btn-ghost | Adopt BEM throughout |
btn--lg | btn-lg | Adopt BEM throughout |
| missing | btn-success | Map to btn--primary + --btn-bg: var(--color-success) |
| missing | btn-outline-white | Add btn--ghost-inverse to DS |
| missing | btn-neutral | Add btn--subtle to DS |
| missing | btn-link, link-btn | Consolidate to one btn--link |
4c. Define a type scale
Pages use 15+ arbitrary font sizes (including half-steps like 11.5px, 13.5px, 14.5px) because the system defines font families but not a scale. Add:
--text-xs: 11px; /* legal, captions, metadata */ --text-sm: 13px; /* labels, helper text, badges */ --text-base: 15px; /* body default */ --text-md: 17px; /* body large, lead text */ --text-lg: 20px; /* card titles, section subheads */ --text-xl: 26px; /* page headings (product surfaces) */ --text-2xl: 34px; /* section headings, hero sub */ --text-3xl: 48px; /* display (brand surfaces only) */
4d. Tokenise placeholder image gradients
Five gradient pairs are used as listing card placeholders across 15+ pages as raw hex. Tokenise them:
--ph-warm-start: #e8d5c4; --ph-warm-end: #c9a382; --ph-green-start: #c5d9c2; --ph-green-end: #8aaa85; --ph-blue-start: #c5d2e0; --ph-blue-end: #8aa2bc; --ph-rose-start: #f4d3d7; --ph-rose-end: #e9aab0; --ph-purple-start: #d4c5e2; --ph-purple-end: #a89fc0;
5. What to Remove
| Item | Reason |
|---|---|
Remove Login v1.html | Uses #E11D2E (wrong brand red), #121212, and 60+ unregistered hex values from a prior system. Dead file that contradicts the current system. |
Review --font-display | If it remains identical to --font-body and no intentional divergence is planned, merge the two. If it is intended as future semantic separation, keep it deliberately and document that intent. The token name carries implicit promise — do not leave it undefined. |
Remove --density: 1 | Defined in :root but never used anywhere. Remove or implement. Dead variables in a source of truth undermine confidence in the file. |
| Remove Half-step font sizes (11.5px, 13.5px, 14.5px) | Signal an undefined scale. They appear where a designer reached for something between two steps. Fix the scale, not the exception. |
Remove Inline style="" colour overrides | Bypass the token system entirely. Invisible to global search. Not auditable. Should be replaced with utility classes or documented component variants. |
Remove sitemap.html reference to #E11D2E | Wrong brand red. Update to --sam-red: #FF6D59. |
6. What to Standardise First
In strict priority order — not time-boxed, because estimates at this stage would be false precision:
- Semantic colour tokens — add to
:rootin the Design System. Zero visual change. Highest leverage because every future page inherits the benefit immediately. - Button class unification — find-replace across 38 files. Mechanical work, no design judgment required. Eliminates the largest single source of implementation confusion.
- Type scale tokens — add 8 variables to
:root, then make a pass replacing arbitrary sizes across pages. - Placeholder gradient tokens — add 10 variables, update page CSS. Straightforward.
- Brand vs product surface rules — document and enforce two clear layout templates (see Section 7). This is the highest-judgment item and should be done after the mechanical fixes above.
- Focus states — add
--border-focustoken and apply consistently to all:focus-visibleselectors on form elements. Accessibility baseline.
Items 1–4 are infrastructure: low judgment, high mechanical effort, immediate payoff. Item 5 requires design leadership. Item 6 requires QA and testing. Do not skip ahead to item 5 before items 1–4 are complete — surface rules applied on top of an inconsistent token system produce inconsistent results.
7. Brand vs Product Surface Rules
Samtrygg operates across two distinct surface contexts. They share the same brand DNA — same typeface, same palette, same component shapes — but they differ fundamentally in intent, density, and visual emphasis. Treating them identically produces pages that are simultaneously over-designed for task completion and under-expressive for brand communication.
- Pages
- Homepage, LandlordLanding, SearchLanding, SafetyPackage, guides, error pages
- Typography
- Nuckle at display sizes (--text-2xl to --text-3xl for heroes). Generous line-height (1.1–1.15 for headings). Body at --text-md (17px).
- Spacing
- Generous vertical rhythm. Section padding --s-8 to --s-9 (96–128px). Let content breathe.
- Surface treatment
- Dark hero sections (--surface-inverse) contrast against warm neutral body (--surface-base). Avoid white-on-white monotony.
- Component density
- Loose. Cards have more internal padding. CTAs are large (btn--lg). Navigation is spacious.
- Visual tone
- Warm, expressive, confident. Colour used actively — not just for feedback. Nuckle at large sizes carries the brand personality.
- Interaction emphasis
- One clear primary CTA per section. Hover states with --shadow-2 lift. Subtle but present animation on key transitions.
- Pages
- All account pages, forms, dashboards, agreements, booking flows, settings
- Typography
- Nuckle at task sizes (--text-xl max for page titles, --text-lg for section heads). Body at --text-base (15px). Tighter line-height (1.5).
- Spacing
- Deliberate. Section padding --s-5 to --s-6 (32–48px). Form groups --s-3 (16px). Density serves scanning, not breathing room.
- Surface treatment
- White cards on --surface-base. Dark topband and footer. Minimal decorative colour — reserve for status communication only.
- Component density
- Standard. Cards use default padding. Buttons are default height unless the action is primary and isolated. Form fields fill available width.
- Visual tone
- Calm, structured, reliable. Colour used almost exclusively for feedback (success/warning/error/info). Brand warmth expressed through the palette neutrals, not bold colour.
- Interaction emphasis
- One primary CTA per form or step. Status clearly communicated at a glance. Focus states always visible. Loading states explicit, not ambiguous.
Applying brand-surface visual density (large type, bold colour, generous spacing) to product surfaces makes forms feel like marketing. Applying product-surface restraint to brand surfaces makes them feel like SaaS. The distinction should be enforced at the layout level, not patched per-component.
CTA hierarchy across surfaces
The current system allows multiple primary buttons per view, which dilutes the signal. The rule should be:
| Surface | Primary CTAs per view | Secondary | Ghost/Link |
|---|---|---|---|
| Brand / marketing | One per section (not per page) | One, at most — paired with primary | Navigation only |
| Product / task | One per form, step, or modal by default | One destructive/cancel action | Utility actions (save draft, view details) |
| Error / empty state | One recovery action | One soft fallback (go back, browse) | None |
8. Component Intent
For each core component: what it is for, and what it is not for. These definitions should govern every future usage decision.
btn--primary is a commitment. btn--secondary is an alternative. btn--ghost is a utility. btn--link is navigation dressed as action.- One
btn--primaryper form or card by default. Duplicate primary actions are only acceptable when they represent the same action in different scroll or viewport contexts. - Destructive actions (delete, cancel) use
btn--danger, always paired with a confirmation step - Never use colour to communicate loading state — use a spinner inside the button
btn--ghoston dark backgrounds requiresbtn--ghost-inverse— do not rely on contrast alone- Disabled state must be visually distinct — use
opacity: 0.45+cursor: not-allowed, never just greyed text
- Static cards have no hover state — adding one implies interactivity
- Interactive cards use
translateY(-2px)+--shadow-2on hover — not border colour change - Never nest interactive elements inside a fully-clickable card — choose one pattern
- Card padding:
--s-4(24px) default on product surfaces,--s-5(32px) on brand surfaces - Card radius should default to
--radius-xl(24px). Smaller radii should only be used if there is a documented system-level reason.
- Default:
--border-defaultborder - Focus:
--border-focusborder +3pxshadow ring at 8% opacity — never colour-only focus - Error:
--border-errorborder + error message directly below, never above - Labels always above the field — never floating labels (they fail on autofill and screen readers)
- Required fields: mark with
*in label — do not rely on placeholder text alone - Disabled:
--surface-sunkenbackground +--text-disabledtext
- Status badges use semantic colours:
--color-success-bg,--color-warning-bg,--color-danger-bg,--color-info-bg - Never use
--sam-redfor a status badge unless it is genuinely an error — the brand red is an action colour, not an alert colour - Badge text should default to uppercase,
--text-xs, font-weight 700, unless a specific readability or localisation case requires otherwise. - Interactive chips: add border, hover state, and
aria-pressed - Limit to 2–3 badges per card — more creates visual noise, not information density
- Four semantic variants only: success, warning, error, info — mapped to
--color-*tokens - Always include an icon alongside colour — colour alone fails for colour-blind users
- Dismissible alerts: always include a visible close affordance (
×or "Dismiss") - Inline errors on form fields are not alerts — they are a component of the input, not a separate component
- Page-level alerts appear below the topband/nav, never inside it
- Do not use alerts for empty states — empty states are their own component
- Maximum 5–6 tabs before content should be restructured into separate pages
- Active tab:
--border-strongunderline (2px), text at full opacity - Inactive tab:
--text-secondary, no underline - Tabs should default to text with underline state, not boxed controls, unless a clearly different navigation pattern is intentionally introduced at system level.
- On mobile: scrollable tab row, not collapsed to select
- Do not use tabs inside modals or drawers — the nesting creates spatial confusion
- Always include: a single icon or illustration, a heading (what's missing), one sentence of explanation (why), one primary CTA (what to do)
- Icon: monochrome, 48–56px, uses
--text-secondarycolour - Heading:
--text-lg, font-weight 700 - Never show an empty state while data is still loading — show a skeleton instead
- Never use the empty state as a loading placeholder — they communicate different things
- On product surfaces: centred, contained within the list area. On brand surfaces: full-section treatment with more generous spacing.
9. Visual Hierarchy, CTA Hierarchy, and Form Communication
Visual hierarchy
The current pages have consistent component styling but inconsistent visual hierarchy within pages. The heading scale is applied locally rather than systematically, which means a --text-xl heading on one page competes with a --text-2xl heading on an adjacent page at the same level of the information architecture.
- Page title → always
--text-xl(26px) on product surfaces - Section heading within a page → always
--text-lg(20px) - Card title → always
--text-baseor--text-md(15–17px) with font-weight 700 - Label / eyebrow → always
--text-xs(11px), uppercase, letter-spacing,--text-secondary - Never use more than three heading levels per page view. If you need four, the information architecture needs restructuring.
Status and form communication
The current system communicates form state primarily through border colour. This is insufficient. Validation, loading, and success states need a fuller communication pattern:
| State | Border | Additional signal | Text |
|---|---|---|---|
| Default | --border-default | — | Label at --text-sm |
| Focus | --border-focus (2px) | 3px ring at 8% opacity | Label unchanged |
| Error | --border-error | Error icon in field trailing position | Error text in --color-danger below field |
| Success (confirmed) | --border-default | Checkmark icon in trailing position | Helper text in --color-success |
| Disabled | --border-default | --surface-sunken background | --text-disabled colour |
| Loading | --border-default | Spinner in trailing position | Label unchanged |
Never rely on colour alone to communicate state. Every colour-based signal must be paired with a shape signal (icon, border weight, or position change). This is both an accessibility requirement and a clarity improvement.
10. Priority Fixes
| # | Issue | Why it matters | Severity | Recommendation |
|---|---|---|---|---|
| 1 | #1a7a3c, #e7f5ed, #8b5a00 etc. used as raw hex on 30+ pages |
Success/warning/danger states have no token. Impossible to update globally. Any brand refresh requires a full codebase hunt. | Critical | Add semantic feedback tokens to :root: --color-success, --color-success-bg, --color-warning, --color-warning-bg, --color-danger-bg, --color-info, --color-info-bg |
| 2 | Two incompatible button class systems (btn--primary vs btn-primary) |
Developers implement both in the same codebase. The DS is not authoritative. Every new page adds to the inconsistency. | Critical | Adopt BEM form (btn--primary) throughout. Mechanical find-replace across all pages. Update Design System to document all variants including new additions. |
| 3 | No type scale tokens — 15+ arbitrary font sizes found | Arbitrary sizes proliferate with each new page. Visual hierarchy is inconsistent because the same information level uses different sizes in different pages. | High | Add --text-xs through --text-3xl to :root. Enforce through DS documentation. Phase out half-step sizes (11.5px, 13.5px, 14.5px). |
| 4 | Placeholder gradient pairs as raw hex in 15 files | Changing the placeholder visual style requires editing 15 files individually. High change cost for low-stakes visual decision. | High | Add --ph-* gradient start/end tokens to :root. Update all usage in one pass. |
| 5 | Brand/product surface distinction not formally defined or enforced | Product pages feel over-designed; brand pages feel under-differentiated. The same spacing and component sizing is applied to both, making neither work optimally. | High | Document brand and product surface rules (see Section 7). Apply to 2–3 representative pages as proof of concept before rolling out. |
| 6 | Multiple primary CTAs per view on several pages | Dilutes the primary action signal. Users hesitate when everything looks equally important. Increases cognitive load at exactly the moment the user should be deciding. | High | Enforce CTA hierarchy rules from Section 7. Audit all pages: one btn--primary per form or step, one secondary, remaining actions as ghost or link. |
| 7 | Focus states not consistently defined across form inputs | Keyboard and assistive technology users cannot reliably track focus position. WCAG 2.1 AA failure. Also a usability issue for all users on forms with many fields. | High | Add --border-focus token. Apply consistent :focus-visible rule to all interactive elements: 2px --border-focus + 3px shadow ring at 8% opacity. |
| 8 | Form validation communicates only via border colour | Fails for colour-blind users. Also insufficient for complex forms where errors may be far from the current scroll position. | Medium | Add icon signal (trailing position) to all error, success, and loading states. Add scroll-to-first-error behaviour on form submit failure. See Section 9 state table. |
| 9 | Inline style="" colour overrides used throughout |
Bypass the token system. Not auditable. Not searchable. Accumulate silently as each page adds local exceptions. | Medium | Extract to utility classes or component variant classes. Establish a rule: no inline colour styles. Exceptions require documentation. |
| 10 | Login v1.html uses #E11D2E (wrong brand red) |
Wrong brand colour in the project. Could be referenced accidentally by a developer unfamiliar with the file history. | Medium | Delete the file. If a reference version is needed, archive it outside the active pages directory. |
| 11 | btn-outline-white (dark bg ghost button) has no DS definition |
Used on dark hero sections but not documented. Each implementation reinvents it slightly differently. Inconsistent appearance on brand surfaces. | Medium | Add btn--ghost-inverse to DS: white border, white text, transparent background. Document usage context (dark surfaces only). |
| 12 | --density: 1 defined but never used |
Dead variable in source of truth. Erodes confidence in the design system file. If it exists, it should do something. | Low | Remove if not planned. Implement if compact/touch modes are on the roadmap — would be high value for mobile product surfaces. |
| 13 | Shadow tokens use rgba(49,49,49,...) not var(--sam-dark) |
Minor inconsistency — the raw colour in shadows is not connected to the colour token. Low practical impact today, but signals a pattern to avoid. | Low | Update shadow tokens to use color-mix(in oklab, var(--sam-dark) 5%, transparent) etc. Address after higher-priority items. |
10a. Change Control
This document is titled a governance document. It requires a lightweight rule set for how the system itself evolves — not just what it currently contains.
All future design system changes should follow these rules:
- No new raw hex values without a token proposal. The token must be named, documented, and added to the Design System before it appears in any page.
- No new component variant without a name, a usage rule, and an implementation pattern. A visual change without these three things is not a variant — it is a local exception.
- No inline colour styles unless explicitly documented as a temporary exception with a named owner and a resolution date.
- Any exception to the system must be documented with the reason and the person responsible. Undocumented exceptions accumulate silently and are the primary source of design drift.
- Design system changes should be reviewed jointly by design and frontend before adoption. Neither discipline owns the system alone.
- The system should be audited quarterly for drift — pages that have diverged from the documented patterns without a corresponding system update.
Exceptions are allowed only when they are documented and intentionally reusable. A local exception that solves only one page is usually a missing token, variant, or component — not a legitimate exception. Treat it as a signal to extend the system, not to bypass it.
11. Final Recommendation
Do not redesign pages. The visual direction is correct. The problem is infrastructure, not aesthetics. Time spent on token consolidation now will reduce effort and inconsistency on every future page.
The Samtrygg design system is at a decision point. It has enough surface area to work — the brand is recognisable, the palette is distinctive, the component shapes are appropriate. But it is missing the governance layer that would make it scale reliably.
The recommended sequence is not a fixed timeline but a dependency graph. Steps 1–4 create the conditions for Step 5 to succeed consistently. Step 5 creates the conditions for new page production to scale. Do not skip ahead.
| Phase | Work | Relative effort | Dependency |
|---|---|---|---|
| Phase 1 Token foundation | Add semantic colour layer, type scale tokens, placeholder tokens. Remove dead variables. Update Design System document. | Low — mechanical, no design judgment | None — do this first |
| Phase 2 Component unification | Unify button classes (BEM). Add missing variants. Define focus states. Update all 38 pages. | Medium — mechanical + light review | Phase 1 complete |
| Phase 3 Surface templates | Write brand surface and product surface rules. Apply to 3 pages each as proof of concept. Document and get sign-off before rolling out. | Medium-high — requires design judgment and stakeholder alignment | Phase 2 complete |
| Phase 4 Form and status | Implement full validation state pattern (icon + colour + text). Add scroll-to-error. Audit CTA hierarchy across all pages. | Medium — requires dev collaboration | Phase 1–2 complete |
| Ongoing Governance | Enforce: no inline colour styles. No new hex values without a token. Every new component documented before shipping. Design System reviewed quarterly. | Low per page — high upfront as habit | Phase 1 complete |
The goal of this document is not to produce a perfect design system immediately. It is to make the next decision easier than the last one — and the one after that easier still. That only happens when the system is trusted, which only happens when it is complete, consistent, and enforced.
12. v1.3 Addendum — April 22, 2026
This addendum captures decisions made during the April 22 polish rundor. None contradict the governance directives above — each extends the system.
| Decision | Rationale | Status |
|---|---|---|
New component: _public-nav drawer (hamburger + slide-in) | Homepage + LandlordLanding hid nav at narrow widths with no replacement. Shared drawer unblocks ≤976px users. | Shipped. Documented in DS § 24. |
New component: _rating (5-star input) | RateExperience.html inlined its own stars. Extracted with Samtrygg.rating API for reuse on future landlord/tenant review flows. | Shipped. Documented. |
New component: _media-upload (drag-drop + reorder) | CreateListing inlined its own uploader. Extracted for reuse on ID verification uploads, listing edits, profile photo changes. | Shipped. CreateListing not yet refactored (avoid publishing-flow regression). |
New component: _bankid (QR auth modal) | BankID pattern lived only as inline panel in Login. Promoted to Samtrygg.bankid.open() helper so other flows (signing, verification) can invoke the same visual. | Shipped. Login not yet refactored. |
| Sidebar badges → runtime-driven | Previous hardcoded "4", "12" etc. blocked server-side integration. Now reads window.SAM_BADGES or localStorage.sam_badges. | Shipped. Razor integrates via <script>window.SAM_BADGES = …</script> in layout. |
| LandlordProfile split from PublicProfile | Reusing tenant-as-seen-by-landlord view as landlord's own-profile edit page was semantically wrong. Separate page added. | Shipped. |
| Desktop filter drawer (Search) | Mobile bottom-sheet was already comprehensive; desktop lacked any deep filter entry. Added right-drawer variant reusing the same .sheet markup. | Shipped. |
Token migration: #faf9f8 → var(--sam-brown-light); #d97706 → var(--color-warning-accent); timeline/agr-card hex removed | Complies with governance § "No hex values without a token". | Shipped in _agreement.css. |
| Spacing normalisation — shared asset files | Core files now stick to 4/8/12/16/20/24/28 scale. Page-specific inline off-grid values remain (~105) — to be addressed per page during integration. | Partial. Core files clean. |
Any new hex literal, off-grid padding, or inline component markup introduced after v1.3 must either reference an existing token/component or file a governance exception. Six components remain un-integrated from their original locations (see Known remainders in DEV_HANDOFF.md) — integrate, don't duplicate.
Brand color contrast — documented WCAG AA exceptions
Lighthouse audit 2026-04-22 flagged the following contrast ratios below WCAG AA 4.5:1. After deliberation, these are accepted brand exceptions, not defects:
| Combination | Ratio | Where used | Decision |
|---|---|---|---|
White text on --sam-red (#FF6D59) | 2.76:1 | Every .btn--primary + .badge--brand across the site | Accepted. Brand-red is core identity; alternative would require either (a) darkening brand red (rejected — brand integrity) or (b) forcing all primary-button text to 18pt+ bold (rejected — visually heavy). |
--sam-red text on --sam-brown-light | 2.36:1 | Hero em accents (hem., Vi tar hand om resten.) | Accepted. Single-word brand emphasis at ≥28px bold. Decorative rather than informational — the meaning is carried by the surrounding black text. |
--sam-red text on #3D3D3D (dark hero) | 3.92:1 | Process-step labels on dark bands | Accepted. ≥14pt bold passes the AA large-text threshold (3:1). |
Muted gray #848484 on white | 3.74:1 | Was: --sam-medium labels, lang-switch inactive, footer org-line | Fixed. --sam-medium darkened to #707070 (4.8:1). Footer secondary gray #6a6a6a → #9e9e9e (4.6:1 on #313131). |
Brand-red exceptions apply only to decorative text and CTA button labels. Any new use of red on white/brown-light outside those contexts must pass 4.5:1 or be restyled.
Samtrygg Design System Governance v1.3 · April 2026 · Design Systems Lead · Samtrygg (Remix)