# Familienarchiv Style Guide

The visual language, component patterns, accessibility rules, and responsive behaviour for the Familienarchiv web application. Informed by De Gruyter brand guidelines and adapted for a dual-audience archival product.

v1.0 2026-03 Leonie Voss · UI/UX Lead

## 1 · Design Philosophy

Core principle

Archival warmth meets functional precision. The Familienarchiv interface is a quiet, focused tool for preserving family memory. It should feel like a well-organised library — warm parchment backgrounds, serif type for human names and content, sans-serif utility chrome — never a social app or consumer product.

Design for the senior researcher on a slow mobile connection in bright daylight first. If it works for them, it works for everyone.

Tone
Calm & purposeful
No decorative animation. No auto-dismissing toasts. No more than 3 focal points per screen. Actions are always available — nothing hides on hover-only.
Information density
Progressive disclosure
Advanced and destructive actions live in collapsible Danger Zone accordions. Filter panels expand when needed, collapse to a strip when not. Desktop can be denser; mobile must be breathable.
Accessibility
WCAG AA as baseline
Every text-background combination must meet WCAG 2.2 AA (4.5:1 for normal text, 3:1 for large text). Body copy targets AAA (7:1). Color is never the only cue — always pair with icon or label.

## 2 · Color System

De Gruyterbrand.degruyter.com
The De Gruyter brand palette is the source of truth for all color decisions. Primary is always black. Secondary colors are used with black only — never combined with each other. Accent colors appear only with black. The Familienarchiv app adapts this system by replacing black-dominant UI with deep navy (#002850) as the primary interactive color to soften the archival aesthetic while staying within the brand's dark-anchor principle.

### De Gruyter Primary

Black — Primary
#000000
Dominates all layouts. Logo, headline type, layout anchoring. Always present.
White
#FFFFFF
Surfaces, cards, form fields. White logo on dark backgrounds.

### De Gruyter Secondary Colors

Use each secondary color only with black — never combine two secondary colors together. Never use white text on Yellow-Green or Mustard.

Yellow-Green
#8A8B1D · PMS 384
⚠ Use BLACK text only. White fails contrast.
Muted Brown
#8C7E5E · PMS 2325
Warm neutrals, archival accents.
Silver
#CACAC9 · PMS 420
Decorative only. Never as text on white — fails contrast.
Blue-Green
#007596 · PMS 7705
5.3:1 on white → WCAG AA ✓ White text on this color.
Magenta
#A81266 · PMS 234
6.8:1 on white → WCAG AA ✓
Granite Gray
#615B66 · PMS 2363
Secondary body text on white only.
Mustard
#AF860E · PMS 1245
⚠ Use BLACK text only. Warning states.

### De Gruyter Accent Colors

Accent colors are used only in combination with black. Never combine two accent colors — exception: data visualizations with a defined key.

Turquoise
#00C7B1
Gold
#FFB81C
9.1:1 on black → WCAG AAA ✓
Lavender
#BF4DA5
Blue
#008AD8
Rose
#F18070
OA Orange
#F18700
Open Access only. Not for general UI.

### Familienarchiv Application Tokens

These CSS custom properties are the concrete values used in the app. They are derived from the De Gruyter palette and the archival aesthetic. Always use these tokens — never hardcode raw hex values in component code.

Token | Value | Preview | Usage
--- | --- | --- | ---
--brand-navy | #002850 |  | Primary interactive color: buttons, active states, key headings, links. Replaces De Gruyter black in UI chrome.
--brand-nav | #0D2240 |  | Navigation bar, sidebars, entity panels. Slightly darker than navy.
--brand-mint | #A6DAD8 |  | Active state underlines, accent borders, hover highlights. Never as standalone text.
--brand-sand | #ECEAE4 |  | Page background. Warm parchment. The breathing room of the layout.
--surface | #FFFFFF |  | Cards, detail panels, form fields, any white surface content lives on.
--surface-alt | #F7F5F2 |  | List panel backgrounds, panel headers, table row alt. One step warmer than white.
--surface-hover | #F0EDE8 |  | Hover state on list items, panel headers.
--border | #E8E4DF |  | Default card and form borders. Warm, not cold gray.
--border-strong | #C8C4BE |  | Section dividers, masthead underlines. Stronger visual separation.
--text-primary | #1A1A1A |  | Body text, list item names. Near-black — softer than pure #000.
--text-secondary | #555555 |  | Secondary descriptors, taglines, form hints.
--text-muted | #888888 |  | Labels, metadata, section headers inside cards. 4.5:1 on white → AA ✓
--text-xmuted | #AAAAAA |  | Decorative only — placeholder text, empty state icons. Never for readable content.
--danger | #DC2626 |  | Destructive actions, error states, required field markers.
--warning | #D97706 |  | Warning banners, unsaved state indicators. Black text on this background.
--success | #15803D |  | Success states, import completion, positive confirmations.

### Contrast Reference

All text combinations must pass WCAG AA. Key pairs used in the app:

Button
14.7:1
AAA
#FFFFFF on #002850 — primary button, nav active
Nav
16.1:1
AAA
#FFFFFF on #0D2240 — navbar, sidebar
Body
18.1:1
AAA
#1A1A1A on #FFFFFF — body text on cards
Page
16.4:1
AAA
#1A1A1A on #ECEAE4 — text on sand background
Label
4.5:1
AA
#888888 on #FFFFFF — section labels, metadata. Minimum passing.
Muted
2.3:1
FAIL
#AAAAAA on #FFFFFF — decorative only, never for real text
DG
5.3:1
AA
White on DG Blue-Green — use white text on this
⚠
2.1:1
FAIL
DG Yellow-Green with white text — always use black text on this
OK
8.6:1
AAA
DG Yellow-Green with black text ✓
⚠
1.6:1
FAIL
DG Silver — decorative only, never as text color on white

### Dark Mode Tokens

Dark mode is not a color inversion. It remaps tokens intentionally across the navy spectrum. The archival warmth is preserved through warm dark backgrounds.

Token | Light value | Dark value | Notes
--- | --- | --- | ---
--bg-page | #ECEAE4 | #0A1628 | Deep navy — not pure black
--bg-surface | #FFFFFF | #0F1E35 | Cards, panels
--bg-surface-alt | #F7F5F2 | #162236 | List panels, alt rows
--bg-nav | #0D2240 | #050E1A | Darker for nav in dark mode
--border | #E8E4DF | #1E3352 |
--border-strong | #C8C4BE | #2A4570 |
--text-primary | #1A1A1A | #E8E6E1 | Warm white, not #FFF
--text-secondary | #555555 | #A8B4C4 |
--text-muted | #888888 | #6B7E96 | Must pass 4.5:1 on dark bg
--brand-navy (interactive) | #002850 | #4A8FD4 | Lightened so links are visible
--brand-mint | #A6DAD8 | #7DC4C0 | Slightly desaturated for dark

✓ Do
Define all colors as CSS custom properties — never hardcode hex values in components
Map light → dark tokens semantically (`--bg-surface` not `--white`)
Use black text on De Gruyter Yellow-Green and Mustard backgrounds
Use white text on --brand-navy and --brand-nav backgrounds
Keep `--text-muted` (#888) as the minimum for readable labels
✕ Don't
Use De Gruyter Silver (#CACAC9) as a text color on white
Combine two De Gruyter secondary or accent colors in the same element
Implement dark mode by simply inverting the light palette
Use `--text-xmuted` (#AAA) for any text that carries meaning
Rely on color alone to convey state (always pair with icon or label)

## 3 · Typography

Two-font system

Montserrat (sans-serif) — UI chrome: labels, buttons, metadata, navigation. Mirrors De Gruyter's Gotham: modern, legible, uppercase for headings.

Merriweather (serif) — Content: person names, document titles, page headings, quoted text. Mirrors De Gruyter's Times: warm, authoritative, human.

### Type Scale

Display · 32px · weight 900 · letter-spacing -1px · Montserrat
Familienarchiv
Masthead, hero headings, marketing copy
Page title · 24px · weight 800 · Merriweather
Personen-Verzeichnis
Page H1, panel headings, person names in detail views
Section title · 20px · weight 800 · Montserrat
Admin — Benutzer & Gruppen
Section headings, card titles in admin
Body · 16px · weight 400 · line-height 1.7 · Merriweather
Die Familie Raddatz lebte von 1887 bis 1943 in Breslau. Diese Sammlung enthält über 240 digitalisierte Briefe, Urkunden und Fotografien aus dem Familienbesitz.
Document summaries, notes fields, any long-form content. Minimum 16px — never smaller.
UI body · 14px · weight 400 · Montserrat
47 Dokumente · Zuletzt bearbeitet 12. März 2026 · Status: Archiviert
Table cells, list item metadata, form descriptions
Label · 11px · weight 800 · uppercase · tracking 2px · Montserrat
Absender · Empfänger · Dokumentenstatus
Form labels, card section headers, table column headers. This is the visual workhorse of the UI chrome.
Caption · 12px · weight 400 · Montserrat
Hochgeladen am 5. März 2026 um 14:32 Uhr
Timestamps, file info, captions. Never below 12px.
Nav link · 10px · weight 700 · uppercase · Montserrat · on dark
Dokumente
Personen
Inactive vs. active nav link. Active gets mint underline, not bold weight change.

### De Gruyter Typography Mapping

De Gruyter role | DG font | App equivalent | Usage context
--- | --- | --- | ---
Headings | Gotham Bold, ALL CAPS | Montserrat 800, uppercase | Section labels, navigation, buttons
Intro text | Gotham Book | Montserrat 400 | UI metadata, captions, descriptions
Body copy | Times Regular | Merriweather Regular | Document content, names, page titles
Captions/footnotes | Gotham Book small | Montserrat 400 12px | Timestamps, file info
Quotes | Times LT Italic/Semibold | Merriweather Italic | Quoted document passages

✓ Do
Use serif (Merriweather) for person names, document titles, page H1s
Use sans-serif (Montserrat) uppercase for all form labels and section headers
Minimum 16px for body text, minimum 12px for any visible text
Line-height 1.6–1.7 for body copy, 1.4 for compact UI text
Use `font-family: Georgia, serif` as fallback until Merriweather loads
✕ Don't
Mix serif and sans-serif within a single label or button
Set any visible text below 12px — use abbreviation, truncation, or tooltip instead
Use uppercase for body text — only for labels and navigation
Use font-weight 900 for anything other than masthead or hero display text
Rely on font-weight alone to distinguish hierarchy — pair with size change

## 4 · Responsive Breakpoints

Design mobile-first. Desktop is an enhancement, not the baseline. Every layout decision starts at 375px and scales up.

📱 Mobile ≤ 639px
Navigation

Hamburger menu or bottom tab bar. Nav items collapse — logo + hamburger icon only in the top bar.

Lists

1-column. Full-width cards stacked vertically.

Detail views

Single column. Sidebar pushes below content. Sticky save bar at bottom of viewport.

Admin / master-detail

Push navigation: list view → push to detail. No side-by-side panels.

Touch targets

Minimum 44×44px. Prefer 48×48px. Primary actions in the thumb zone (bottom 2/3 of screen).

Filter panels

Full-screen overlay. Opened via "Filter" button, dismissed with "Anwenden".

📱 Tablet 640–1023px
Navigation

Full top navbar visible. Entity nav sidebar collapses to 48px icon strip with tooltip on hover.

Lists

2-column grids. Person cards in 2 columns.

Detail views

Single column stacked (same as mobile). Sidebar below content.

Admin / master-detail

List panel collapsible: 240px expanded ↔ 32px collapsed handle. Detail panel fills remaining space.

Filter panels

Collapsible inline strip (collapsed) or full filter panel (expanded). Strip shows active filter summary.

Forms

Full-page form. Two-column field rows acceptable where fields are short (e.g., birth/death dates).

🖥 Desktop ≥ 1024px
Navigation

Full top navbar + 120px entity nav sidebar (full labels + counts visible).

Lists

4-column grids for person/document cards. Dense list views with inline actions.

Detail views

2-column sidebar (35%) + main content (65%). Person card + activity area side by side.

Admin / master-detail

3 persistent panels: Entity Nav (120px) + List Panel (240px) + Detail Panel (remaining). All visible simultaneously.

Filter panels

Inline collapsed strip by default. Expands to a full filter card above the list.

Max content width

1560px. Content always centered. Padding: 48px vertical, 32px horizontal.

### Layout Anatomy — Desktop Admin (1440px)

FAMILIENARCHIV Dokumente Personen Admin M. Raddatz
Entitäten
Benutzer
12
Gruppen
4
Tags
38
Benutzer
Suche…
Anna Raddatz ›
Bernd Schiller ›
Claudia Werner ›
Anna Raddatz
anna@example.com · Mitglied seit 2024
Bearbeiten
Detail-Inhalt hier
✓ Do
Start every layout at 375px viewport width before designing desktop
Use CSS Grid and `minmax()` for responsive columns — no fixed-pixel column widths
Test at 320px, 375px, 640px, 768px, 1024px, 1440px
Keep the meta viewport tag: `<meta name="viewport" content="width=device-width, initial-scale=1">`
Use `min-height: 44px` on all tappable elements
✕ Don't
Set fixed pixel widths on layout columns below 1024px
Show three-panel master-detail layout at 768px — use collapsible list panel
Design desktop-first and then "shrink down" — information gets lost
Hide content that exists on desktop from mobile — stack it instead
Use hover-only interactions as the primary way to discover actions

## 5 · Components

### 5.1 · Navigation Bar

Height: 44px · Background: #0D2240 · Active link: white + 2px #A6DAD8 underline · Inactive link: rgba(255,255,255,.5)

✓ Do
Mark active page with white text + 2px mint bottom border
Keep logo text always white and at left edge
Ensure all nav links have visible focus ring (test with keyboard)
Add `aria-current="page"` to the active nav link
✕ Don't
Remove focus outline from nav links without a custom focus style
Use color alone to indicate the active page
Collapse the navbar to a hamburger on desktop widths
Put more than 5 top-level nav items in the navbar

### 5.2 · Buttons

Sizes: default (40px height) · small (32px) · All uppercase · font-weight 700 · letter-spacing .5px

Focus ring: `outline: 3px solid rgba(0,40,80,.4); outline-offset: 2px` — never remove without replacement

✓ Do
Use btn-primary for the single most important action per screen
Place destructive actions (btn-danger) away from primary actions — space them
Always include a visible focus ring — use rgba navy shadow, not browser default
Minimum button height 40px (desktop), 44px (mobile / touch)
Add `aria-label` to icon-only buttons: `<button aria-label="Löschen">`
✕ Don't
Use `outline: none` or `outline: 0` without a custom focus replacement
Place two primary buttons next to each other
Use btn-danger-fill for anything other than a final irreversible action
Make button text all lowercase — all buttons are uppercase in this system
Use icon-only buttons without an aria-label or visible tooltip

### 5.3 · Cards

Dokument
Brief an Tante Frieda, Weihnachten 1932
Von: Karl Raddatz · An: Frieda Schiller
Transkribiert Brief
25. Dez. 1932

Background: #FFFFFF · Border: 1.5px solid #E8E4DF · border-radius: 8px · padding: 20–24px · shadow-sm

Card variant | Use case | Border
--- | --- | ---
Default card | Content sections, detail panels | `1.5px solid #E8E4DF`
Hover card (list grid) | Person/doc cards in grid view | `1.5px solid #A6DAD8` + left accent 3px mint
Selected (master-detail) | Active list item in panel | `border-right: 3px solid #002850` + #EEF2FF bg
Warning card | Pending import, unsaved state | `1.5px solid #FDE68A` + #FFFBEB bg
Danger zone | Destructive actions section | `1.5px solid #FCA5A5` + #FFF5F5 bg

### 5.4 · Forms

Vorname *
Vollständiger Vorname der Person
Nachname *
Dieser Name existiert bereits.

Input default: bg #F9FAFB · border #D1D5DB · height 40px · Focus: border #002850 + 3px rgba ring · Error: border #DC2626 + bg #FFF5F5

✓ Do
Always use a visible `<label>` associated with each input via `for/id`
Mark required fields with red asterisk * AND a legend note
Show error text below the field — not in a toast that auto-dismisses
Use the sticky save bar pattern for long forms
Minimum input height 40px (desktop), 44px (mobile)
✕ Don't
Use placeholder text as the only label — it disappears on focus
Use red border alone to signal an error — add text explanation
Auto-dismiss error messages without a manual dismiss option
Disable the submit button while form is pristine — use server validation instead
Place more than 3 fields in a horizontal row

### 5.5 · Status Chips & Badges

Archiviert Transkribiert Ausstehend Fehler Hochgeladen Entwurf
Platzhalter — Datei noch nicht hochgeladen
Hochgeladen
Transkribiert
Geprüft
Archiviert

Status dots are always paired with a text label. Never use color alone for document lifecycle state.

### 5.6 · Alerts & Banners

ℹ Der Import läuft im Hintergrund. Dies kann einige Minuten dauern.
⚠Es gibt ungespeicherte Änderungen. Bitte speichern Sie, bevor Sie die Seite verlassen.
✕Der Datei-Upload ist fehlgeschlagen. Maximal 50 MB pro Datei erlaubt.
✓15 Dokumente wurden erfolgreich importiert.
✓ Do
Include an icon + text in every alert (never color-only)
Add `role="alert"` for error messages, `role="status"` for info banners
For seniors: persistent banners stay visible until manually dismissed
Place banners above the related content area, not floating over it
✕ Don't
Auto-dismiss error or warning toasts on a timer
Stack more than 2 alerts in the same view
Use generic "An error occurred" — specify what failed and what to do
Show success alerts for trivial operations (e.g. typing a character)

### 5.7 · Empty States

📂
Keine Personen gefunden
Versuchen Sie einen anderen Suchbegriff oder legen Sie eine neue Person an.
Neue Person anlegen

Border: 2px dashed #D1CCC8 · bg #F7F5F2 · Icon in 48px circle · Serif heading · CTA button

### 5.8 · Danger Zone

⚠ Gefahrenzone
Diese Aktionen können nicht rückgängig gemacht werden. Bitte lesen Sie die Beschreibung sorgfältig, bevor Sie fortfahren.
Geben Sie zur Bestätigung den Namen "Anna Raddatz" ein:

Always hidden in a collapsed accordion on load. Require typed confirmation for irreversible delete actions.

### 5.9 · Save Bar

Long forms (edit document, edit person): sticky, full-bleed

Ungespeicherte Änderungen

Short forms (new person, new tag): card-style with top margin

## 6 · Dark Mode

Dark mode is available by default (millennial preference). It uses the deep navy spectrum — not grey or black — preserving the archival warmth in dark contexts. Always verify contrast ratios after remapping tokens.

Dokument
Brief an Tante Frieda, Weihnachten 1932
Von: Karl Raddatz · An: Frieda Schiller
Suchfeld

Dark mode palette: page bg #0A1628 · surface #0F1E35 · text #E8E6E1 · muted text #6B7E96 · interactive #4A8FD4 · mint #7DC4C0

✓ Do
Use `prefers-color-scheme: dark` as the CSS media query trigger
Lighten interactive colors for dark mode (#4A8FD4 instead of #002850)
Use warm near-white (#E8E6E1) instead of pure white for text on dark
Re-verify every text-background contrast pair in dark mode separately
Keep mint accent (#7DC4C0) for active states — slightly desaturated from light mode
✕ Don't
Simply invert the light mode palette — this breaks the visual hierarchy
Use pure black (#000) as the dark background — too harsh
Use the same #002850 navy as interactive color — it disappears on dark bg
Hardcode colors in components — always use CSS custom properties
Assume light mode contrast ratios carry over to dark mode

## 7 · Accessibility — WCAG 2.2

Dual-audience requirement

Familienarchiv serves both millennials (25–42) and seniors (60+). The senior constraint is the design driver: it almost always improves the millennial experience too. If a 67-year-old professor on mobile in sunlight can use it, everyone can.

1.4.3 — AA
Contrast Ratio: Text
Normal text (below 18px regular / 14px bold): minimum 4.5:1. Large text (18px+ regular or 14px+ bold): minimum 3:1. Body copy target: 7:1 (AAA).
Label text #888 on white: 4.5:1 ✓
Body text #1A1A1A on white: 18.1:1 ✓
1.4.11 — AA
Non-text Contrast
UI components (form borders, focus rings, icons) need 3:1 contrast against their background. A #D1D5DB form border on white = 1.9:1 — add focus state immediately.
Form border #D1D5DB on white: 1.9:1 (fails — acceptable only when focus state at 3:1+ compensates)
2.4.7 — AA
Focus Visible
Every interactive element must have a clearly visible focus indicator. Use `outline: 3px solid rgba(0,40,80,.4); outline-offset: 2px`. Never `outline: none` without replacement.
1.3.1 — A
Info & Relationships
Form labels must be programmatically associated with inputs. Section headings must use correct heading elements. Status colors must have text or icon pairing.
Bad: `<div class="label">` + `<input>`
Good: `<label for="name">` + `<input id="name">`
1.4.6 — AAA (target)
Enhanced Contrast (Body)
Body copy and person names must target 7:1 contrast ratio — AAA level. This serves seniors and outdoor mobile use. Use #1A1A1A on white (18.1:1) and #0D2240 on white (18.6:1).
2.5.3 — A
Label in Name
The accessible name of a button must contain its visible text. Icon-only buttons need `aria-label`. Visible "Speichern" button → `aria-label` must include "Speichern".
2.4.3 — A
Focus Order
Tab order must match visual reading order. Modal dialogs trap focus. On mobile, the sticky save bar must be reachable by keyboard. Avoid `tabindex` values above 0.
4.1.3 — AA
Status Messages
Dynamically injected alerts must be announced by screen readers without receiving focus. Use `role="alert"` for errors, `role="status"` for non-critical updates (import progress).

### Seniors (60+) — Additional Requirements

Text & Readability
Minimum 16px body text — prefer 18px
Line-height minimum 1.6 for all body copy
Paragraph spacing minimum 0.5em
No text below 12px for any visible content
Avoid italic text for long passages
Interaction
Touch targets minimum 44×44px, prefer 48px
Persistent primary navigation always visible
No timed interactions or auto-advancing content
Redundant cues: color + icon + text label
Max 3 focal points per screen on mobile

### Semantic HTML Landmarks

Every page must contain these landmark elements to enable screen reader navigation:

Element | Purpose | Required
--- | --- | ---
`<header>` | Site navigation bar | ✓ Always
`<nav>` | Primary navigation links with `aria-label="Hauptnavigation"` | ✓ Always
`<main>` | Main page content — only one per page | ✓ Always
`<footer>` | Page footer with meta links | ✓ Always
`<aside>` | Sidebar panels (person card, filter panel) | When sidebar present
`role="dialog"` + `aria-modal="true"` | Modal overlays (confirm delete) | When modal present

## 8 · Spacing & Layout Rhythm

Spacing follows a 4px base grid. All values are multiples of 4. Key values in the component system:

Token | Value | Usage
--- | --- | ---
--space-1 | 4px | Icon gaps, tight inline spacing
--space-2 | 8px | Chip gaps, input inner padding
--space-3 | 12px | Card inner padding (compact), list item padding
--space-4 | 16px | Form group spacing, section body padding
--space-5 | 20px | Card padding (default), panel padding
--space-6 | 24px | Section gap, grid gap on mobile
--space-8 | 32px | Page horizontal padding, section separation
--space-12 | 48px | Page top/bottom padding, masthead padding
--space-18 | 72px | Section-to-section gap

Panel system

Entity Nav: 120px (desktop), 48px icon strip (tablet), hidden (mobile). List Panel: 240px (desktop), collapsible to 32px handle (tablet), full-screen push (mobile). Detail Panel: fills remaining space. Total fixed columns on desktop: 120 + 240 = 360px out of ~1200px viewport.

## 9 · Quick Reference

Things you must always do
Visible focus ring on every interactive element
Color + icon/text together for any status indication
`<label for>` on every form input
`aria-label` on every icon-only button
Start design at 375px, test at 320px
CSS custom properties for every color value
44px minimum touch target height on mobile
role="alert" on dynamically injected error messages
main, nav, header, footer landmarks on every page
Typed confirmation for irreversible delete actions
Things you must never do
`outline: none` without a custom focus replacement
Color alone to convey state (error, success, status)
Text below 12px in production
Auto-dismiss error or warning toasts
White text on De Gruyter Yellow-Green (#8A8B1D)
Silver (#CACAC9) as text color on white
Combine two De Gruyter secondary colors
Dark mode as a simple light-mode inversion
Hardcode hex values in components
Design desktop-first and shrink to mobile
Familienarchiv Style Guide · v1.0 · 2026-03
Leonie Voss · UI/UX Lead · Based on De Gruyter brand guidelines