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

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.

TokenLight valueDark valueNotes
--bg-page#ECEAE4#0A1628Deep navy — not pure black
--bg-surface#FFFFFF#0F1E35Cards, panels
--bg-surface-alt#F7F5F2#162236List panels, alt rows
--bg-nav#0D2240#050E1ADarker for nav in dark mode
--border#E8E4DF#1E3352
--border-strong#C8C4BE#2A4570
--text-primary#1A1A1A#E8E6E1Warm white, not #FFF
--text-secondary#555555#A8B4C4
--text-muted#888888#6B7E96Must pass 4.5:1 on dark bg
--brand-navy (interactive)#002850#4A8FD4Lightened so links are visible
--brand-mint#A6DAD8#7DC4C0Slightly 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 roleDG fontApp equivalentUsage context
HeadingsGotham Bold, ALL CAPSMontserrat 800, uppercaseSection labels, navigation, buttons
Intro textGotham BookMontserrat 400UI metadata, captions, descriptions
Body copyTimes RegularMerriweather RegularDocument content, names, page titles
Captions/footnotesGotham Book smallMontserrat 400 12pxTimestamps, file info
QuotesTimes LT Italic/SemiboldMerriweather ItalicQuoted 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 variantUse caseBorder
Default cardContent sections, detail panels1.5px solid #E8E4DF
Hover card (list grid)Person/doc cards in grid view1.5px solid #A6DAD8 + left accent 3px mint
Selected (master-detail)Active list item in panelborder-right: 3px solid #002850 + #EEF2FF bg
Warning cardPending import, unsaved state1.5px solid #FDE68A + #FFFBEB bg
Danger zoneDestructive actions section1.5px solid #FCA5A5 + #FFF5F5 bg

5.4 · Forms

Vollständiger Vorname der Person
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.

FAMILIENARCHIV Dokumente Personen M. Raddatz
Dokument
Brief an Tante Frieda, Weihnachten 1932
Von: Karl Raddatz · An: Frieda Schiller

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:

ElementPurposeRequired
<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:

TokenValueUsage
--space-14pxIcon gaps, tight inline spacing
--space-28pxChip gaps, input inner padding
--space-312pxCard inner padding (compact), list item padding
--space-416pxForm group spacing, section body padding
--space-520pxCard padding (default), panel padding
--space-624pxSection gap, grid gap on mobile
--space-832pxPage horizontal padding, section separation
--space-1248pxPage top/bottom padding, masthead padding
--space-1872pxSection-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