Files
familienarchiv/docs/style-guide.html
2026-04-14 23:21:15 +02:00

1404 lines
85 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Familienarchiv — Visual Style Guide</title>
<style>
/* ── Reset ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{font-size:16px;scroll-behavior:smooth}
body{font-family:'Helvetica Neue',Arial,sans-serif;background:#ECEAE4;color:#1A1A1A;line-height:1.6}
/* ── Layout ── */
.page{max-width:1200px;margin:0 auto;padding:48px 32px 96px}
.section{margin-bottom:80px}
.section+.section{border-top:2px dashed #C8C4BE;padding-top:72px}
h2.section-title{font-size:11px;font-weight:800;color:#888;text-transform:uppercase;letter-spacing:2px;margin-bottom:24px;display:flex;align-items:center;gap:12px}
h2.section-title::after{content:'';flex:1;height:1px;background:#D8D4CE}
h3.sub-title{font-size:16px;font-weight:800;color:#0D2240;margin-bottom:12px;margin-top:32px}
h3.sub-title:first-child{margin-top:0}
p.desc{font-size:14px;color:#555;line-height:1.7;max-width:720px;margin-bottom:20px}
code{font-family:monospace;font-size:12px;background:#F3F4F6;border:1px solid #E5E7EB;padding:1px 5px;border-radius:3px;color:#1A1A1A}
/* ── Masthead ── */
.masthead{background:#0D2240;border-radius:12px;padding:48px 48px 40px;margin-bottom:64px;position:relative;overflow:hidden}
.masthead::before{content:'';position:absolute;top:-60px;right:-60px;width:300px;height:300px;background:rgba(166,218,216,.07);border-radius:50%}
.masthead::after{content:'';position:absolute;bottom:-40px;left:20%;width:200px;height:200px;background:rgba(166,218,216,.05);border-radius:50%}
.masthead h1{font-size:32px;font-weight:900;color:#fff;letter-spacing:-1px;margin-bottom:10px;position:relative}
.masthead h1 span{color:#A6DAD8}
.masthead p{font-size:14px;color:rgba(255,255,255,.55);max-width:680px;line-height:1.7;position:relative}
.masthead-meta{margin-top:20px;display:flex;gap:10px;flex-wrap:wrap;position:relative}
.meta-badge{font-size:10px;font-weight:800;padding:4px 12px;border-radius:20px;text-transform:uppercase;letter-spacing:.8px}
.mb-version{background:#A6DAD8;color:#002850}
.mb-date{background:rgba(255,255,255,.1);color:rgba(255,255,255,.6)}
.mb-author{background:rgba(166,218,216,.15);color:#A6DAD8;border:1px solid rgba(166,218,216,.3)}
/* ── Color swatches ── */
.swatch-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px;margin-bottom:20px}
.swatch{border-radius:8px;overflow:hidden;border:1px solid rgba(0,0,0,.08)}
.swatch-color{height:72px}
.swatch-info{padding:10px 12px;background:#fff}
.swatch-name{font-size:11px;font-weight:700;color:#1A1A1A;margin-bottom:2px}
.swatch-hex{font-family:monospace;font-size:11px;color:#666}
.swatch-rule{font-size:10px;color:#999;margin-top:3px;line-height:1.4}
.swatch-row{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.swatch-sm{width:48px;height:48px;border-radius:6px;border:1px solid rgba(0,0,0,.1);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:800;flex-shrink:0}
/* ── Token table ── */
.token-table{width:100%;border-collapse:collapse;font-size:13px;margin-bottom:24px}
.token-table th{text-align:left;padding:10px 14px;font-size:11px;font-weight:800;color:#888;text-transform:uppercase;letter-spacing:.5px;border-bottom:2px solid #E8E4DF;background:#F7F5F2}
.token-table td{padding:9px 14px;border-bottom:1px solid #F0EDE6;color:#444;vertical-align:top}
.token-table tr:last-child td{border-bottom:none}
.token-table td:first-child{font-family:monospace;font-size:12px;color:#002850;white-space:nowrap}
.dot-preview{display:inline-block;width:16px;height:16px;border-radius:4px;border:1px solid rgba(0,0,0,.1);vertical-align:middle;margin-right:6px}
/* ── Typography specimens ── */
.type-specimen{margin-bottom:16px;padding:20px 24px;background:#fff;border:1px solid #E8E4DF;border-radius:8px}
.type-meta{font-size:10px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:1.5px;margin-bottom:8px}
.type-label{font-size:10px;color:#999;margin-top:6px}
/* ── Breakpoint grid ── */
.bp-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-bottom:24px}
.bp-card{background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;overflow:hidden}
.bp-header{padding:12px 16px;border-bottom:1px solid #E8E4DF;display:flex;align-items:center;justify-content:space-between}
.bp-label{font-size:11px;font-weight:800;color:#0D2240}
.bp-px{font-family:monospace;font-size:11px;color:#888}
.bp-body{padding:16px}
.bp-body p{font-size:12px;color:#555;line-height:1.6;margin-bottom:8px}
.bp-body p:last-child{margin-bottom:0}
.bp-rule{font-size:11px;font-weight:700;color:#002850;margin-bottom:3px}
/* ── Do / Don't ── */
.do-dont{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1.5px solid #E0DDD6;border-radius:8px;overflow:hidden;margin-bottom:24px}
.do-dont-col{}
.do-dont-head{padding:10px 16px;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;border-bottom:1.5px solid #E0DDD6}
.do-head{background:#F0FDF4;color:#166534;border-right:1px solid #E0DDD6}
.dont-head{background:#FFF5F5;color:#991B1B}
.do-dont-body{padding:20px;background:#fff}
.do-dont-col:first-child .do-dont-body{border-right:1px solid #F0EDE6;background:#FAFFFE}
.do-dont-col:last-child .do-dont-body{background:#FFFAFA}
.rule-item{font-size:13px;color:#444;padding:5px 0;line-height:1.5;display:flex;align-items:flex-start;gap:8px}
.rule-item::before{flex-shrink:0;margin-top:2px;font-size:12px;font-weight:700}
.do-item::before{content:'✓';color:#16A34A}
.dont-item::before{content:'✕';color:#DC2626}
.rule-item code{font-size:11px}
/* ── WCAG table ── */
.wcag-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}
.wcag-card{background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:16px 18px}
.wcag-level{display:inline-block;font-size:9px;font-weight:800;padding:2px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:10px}
.wcag-aa{background:#DBEAFE;color:#1E40AF}
.wcag-aaa{background:#DCFCE7;color:#166534}
.wcag-fail{background:#FEE2E2;color:#991B1B}
.wcag-title{font-size:13px;font-weight:800;color:#1A1A1A;margin-bottom:6px}
.wcag-desc{font-size:12px;color:#555;line-height:1.6}
.wcag-example{margin-top:12px;padding:10px 12px;border-radius:5px;font-size:13px}
.contrast-row{display:flex;align-items:center;gap:12px;padding:8px 0;border-bottom:1px solid #F0EDE6;font-size:12px}
.contrast-row:last-child{border-bottom:none}
.contrast-chip{width:80px;height:28px;border-radius:4px;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;flex-shrink:0}
.contrast-ratio{font-family:monospace;font-weight:700;color:#1A1A1A;width:50px;flex-shrink:0}
.contrast-status{font-size:10px;font-weight:800;padding:2px 6px;border-radius:3px;flex-shrink:0}
.pass-aa{background:#DCFCE7;color:#166534}
.pass-aaa{background:#DBEAFE;color:#1E40AF}
.fail-c{background:#FEE2E2;color:#991B1B}
.contrast-desc{color:#666}
/* ── Component previews ── */
.preview-box{background:#F7F5F2;border:1.5px solid #E0DDD6;border-radius:8px;padding:24px;margin-bottom:16px}
.preview-box.dark{background:#0D2240}
.preview-box.light{background:#fff}
/* ── Nav preview ── */
.nav-preview{height:44px;background:#0D2240;border-radius:6px;display:flex;align-items:center;padding:0 18px;gap:14px;margin-bottom:8px}
.nav-logo{font-size:11px;font-weight:900;color:#fff;letter-spacing:1px}
.nav-link{font-size:10px;color:rgba(255,255,255,.5);font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding-bottom:2px}
.nav-link.active{color:#fff;border-bottom:2px solid #A6DAD8}
.nav-right{margin-left:auto;display:flex;gap:8px;align-items:center}
.nav-icon{width:24px;height:24px;background:rgba(255,255,255,.12);border-radius:5px}
.nav-user{font-size:10px;color:rgba(255,255,255,.6);font-weight:700}
/* ── Button previews ── */
.btn-row{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:12px}
.btn{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:700;padding:9px 18px;border-radius:5px;cursor:pointer;text-transform:uppercase;letter-spacing:.5px;font-family:inherit;border:none;text-decoration:none}
.btn-primary{background:#002850;color:#fff}
.btn-primary:hover{background:#003875}
.btn-outline{border:1.5px solid #002850;color:#002850;background:transparent;padding:8px 17px}
.btn-ghost{color:#555;background:transparent;padding:8px 12px}
.btn-danger{border:1.5px solid #DC2626;color:#DC2626;background:#FEF2F2;padding:8px 17px}
.btn-danger-fill{background:#DC2626;color:#fff}
.btn-sm{font-size:11px;padding:6px 12px}
.btn-disabled{opacity:.4;cursor:not-allowed}
.btn-focus-example{outline:3px solid rgba(0,40,80,.4);outline-offset:2px;background:#002850;color:#fff}
/* ── Card previews ── */
.card{background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:20px 22px;margin-bottom:12px}
.card-heading{font-size:10px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:2px;margin-bottom:16px}
.card-title{font-size:18px;font-weight:800;color:#0D2240;font-family:Georgia,serif;margin-bottom:6px}
.card-sub{font-size:13px;color:#666}
/* ── Form previews ── */
.form-group{margin-bottom:16px}
.form-label{display:block;font-size:11px;font-weight:800;color:#888;text-transform:uppercase;letter-spacing:.5px;margin-bottom:5px}
.form-label .req{color:#DC2626}
.form-input{width:100%;max-width:360px;height:40px;border:1.5px solid #D1D5DB;border-radius:5px;background:#F9FAFB;padding:0 12px;font-size:14px;font-family:inherit;color:#1A1A1A}
.form-input:focus{outline:3px solid rgba(0,40,80,.15);border-color:#002850;background:#fff}
.form-input.error{border-color:#DC2626;background:#FFF5F5}
.form-error{font-size:12px;color:#DC2626;margin-top:4px}
.form-hint{font-size:12px;color:#888;margin-top:4px}
/* ── Chip previews ── */
.chip-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.chip{display:inline-flex;align-items:center;font-size:11px;font-weight:700;padding:3px 10px;border-radius:12px;text-transform:uppercase;letter-spacing:.3px}
.chip-navy{background:#EEF2FF;color:#002850;border:1px solid #C7D2FE}
.chip-mint{background:#D6F0EE;color:#0F5B58;border:1px solid #A6DAD8}
.chip-amber{background:#FEF9C3;color:#854D0E;border:1px solid #FEF08A}
.chip-red{background:#FEE2E2;color:#991B1B;border:1px solid #FCA5A5}
.chip-green{background:#DCFCE7;color:#166534;border:1px solid #BBF7D0}
.chip-gray{background:#F3F4F6;color:#374151;border:1px solid #E5E7EB}
/* ── Alert previews ── */
.alert{padding:12px 16px;border-radius:6px;font-size:13px;line-height:1.6;margin-bottom:10px;display:flex;align-items:flex-start;gap:10px}
.alert-icon{font-size:16px;flex-shrink:0;margin-top:1px}
.alert-info{background:#EFF6FF;border:1px solid #BFDBFE;color:#1E40AF}
.alert-warn{background:#FFFBEB;border:1px solid #FDE68A;color:#92400E}
.alert-err{background:#FEF2F2;border:1px solid #FCA5A5;color:#991B1B}
.alert-ok{background:#F0FDF4;border:1px solid #BBF7D0;color:#166534}
/* ── Empty state ── */
.empty-state{border:2px dashed #D1CCC8;border-radius:8px;padding:40px 24px;text-align:center;background:#F7F5F2;display:flex;flex-direction:column;align-items:center;gap:10px}
.empty-icon{width:48px;height:48px;border-radius:50%;background:#E8E4DF;display:flex;align-items:center;justify-content:center;font-size:22px}
.empty-h{font-size:16px;font-weight:700;color:#444;font-family:Georgia,serif}
.empty-s{font-size:13px;color:#999;max-width:280px;line-height:1.5}
.empty-cta{font-size:11px;font-weight:800;background:#002850;color:#fff;padding:8px 18px;border-radius:5px;text-transform:uppercase;letter-spacing:.5px;margin-top:4px;cursor:pointer}
/* ── Danger zone ── */
.danger-zone{border:1.5px solid #FCA5A5;border-radius:8px;padding:16px 18px;background:#FFF5F5}
.danger-title{font-size:13px;font-weight:800;color:#991B1B;margin-bottom:6px;display:flex;align-items:center;gap:8px}
.danger-desc{font-size:12px;color:#777;line-height:1.6;margin-bottom:12px}
.danger-confirm{background:#FEE2E2;border:1.5px solid #FCA5A5;border-radius:5px;padding:12px 14px}
.danger-confirm-msg{font-size:12px;color:#7F1D1D;font-weight:600;margin-bottom:8px}
/* ── Save bar ── */
.save-bar{background:#fff;border-top:1.5px solid #E8E4DF;padding:12px 20px;display:flex;align-items:center;justify-content:space-between;box-shadow:0 -2px 8px rgba(0,0,0,.06);border-radius:0 0 8px 8px}
.save-bar-sticky{background:#fff;border-top:1.5px solid #E8E4DF;padding:12px 20px;display:flex;align-items:center;justify-content:space-between;box-shadow:0 -2px 8px rgba(0,0,0,.06)}
/* ── Dark mode preview ── */
.dark-preview{background:#0A1628;border-radius:8px;padding:24px;color:#E8E6E1}
.dark-nav{height:44px;background:#050E1A;border-radius:6px 6px 0 0;display:flex;align-items:center;padding:0 18px;gap:14px;margin:-24px -24px 20px}
.dark-card{background:#0F1E35;border:1.5px solid #1E3352;border-radius:8px;padding:16px 18px;margin-bottom:12px}
.dark-card-heading{font-size:10px;font-weight:800;color:#4A6080;text-transform:uppercase;letter-spacing:2px;margin-bottom:12px}
.dark-card-title{font-size:16px;font-weight:700;color:#E8E6E1;font-family:Georgia,serif;margin-bottom:4px}
.dark-card-sub{font-size:13px;color:#7896B4}
.dark-input{width:100%;max-width:320px;height:40px;border:1.5px solid #1E3352;border-radius:5px;background:#0A1628;padding:0 12px;font-size:14px;font-family:inherit;color:#E8E6E1}
.dark-btn-primary{background:#3A7CC4;color:#fff;border:none}
.dark-btn-outline{border:1.5px solid #3A7CC4;color:#7DB8E8;background:transparent}
/* ── Responsive note ── */
.resp-note{font-size:12px;color:#888;font-style:italic;margin-top:8px}
/* ── Status dots ── */
.status-row{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:13px;color:#444}
.status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
/* ── Callout box ── */
.callout{background:#F0F7FF;border-left:4px solid #002850;border-radius:0 6px 6px 0;border:1px solid #BFDBFE;border-left:4px solid #002850;padding:14px 18px;margin-bottom:24px}
.callout-title{font-size:11px;font-weight:800;color:#002850;text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}
.callout p{font-size:13px;color:#1E3A5F;line-height:1.6}
.callout p+p{margin-top:6px}
/* ── Divider ── */
hr.rule{border:none;border-top:1px solid #E8E4DF;margin:24px 0}
/* ── DG brand section ── */
.dg-intro{background:#000;border-radius:8px;padding:24px 28px;margin-bottom:24px;display:flex;align-items:flex-start;gap:20px}
.dg-logo{font-size:18px;font-weight:900;color:#fff;letter-spacing:1px;flex-shrink:0;line-height:1}
.dg-logo span{display:block;font-size:11px;font-weight:400;color:rgba(255,255,255,.5);letter-spacing:2px;margin-top:4px}
.dg-intro-text{font-size:13px;color:rgba(255,255,255,.6);line-height:1.6}
.dg-intro-text strong{color:rgba(255,255,255,.9)}
/* ── App adaptation note ── */
.adapt-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}
.adapt-card{background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:16px 18px}
.adapt-label{font-size:10px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:1px;margin-bottom:8px}
.adapt-title{font-size:14px;font-weight:800;color:#1A1A1A;margin-bottom:6px}
.adapt-text{font-size:12px;color:#555;line-height:1.6}
/* ── Print/focus note ── */
@media (prefers-reduced-motion: reduce){
*{animation:none!important;transition:none!important}
}
</style>
</head>
<body>
<div class="page">
<!-- ══ MASTHEAD ══ -->
<div class="masthead">
<h1>Familienarchiv <span>Style Guide</span></h1>
<p>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.</p>
<div class="masthead-meta">
<span class="meta-badge mb-version">v1.0</span>
<span class="meta-badge mb-date">2026-03</span>
<span class="meta-badge mb-author">Leonie Voss · UI/UX Lead</span>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 1 · DESIGN PHILOSOPHY -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">1 · Design Philosophy</h2>
<div class="callout">
<div class="callout-title">Core principle</div>
<p><strong>Archival warmth meets functional precision.</strong> 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.</p>
<p>Design for the senior researcher on a slow mobile connection in bright daylight first. If it works for them, it works for everyone.</p>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px">
<div class="adapt-card">
<div class="adapt-label">Tone</div>
<div class="adapt-title">Calm & purposeful</div>
<div class="adapt-text">No decorative animation. No auto-dismissing toasts. No more than 3 focal points per screen. Actions are always available — nothing hides on hover-only.</div>
</div>
<div class="adapt-card">
<div class="adapt-label">Information density</div>
<div class="adapt-title">Progressive disclosure</div>
<div class="adapt-text">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.</div>
</div>
<div class="adapt-card">
<div class="adapt-label">Accessibility</div>
<div class="adapt-title">WCAG AA as baseline</div>
<div class="adapt-text">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.</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 2 · COLOR SYSTEM -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">2 · Color System</h2>
<!-- De Gruyter brand source -->
<div class="dg-intro">
<div class="dg-logo">De Gruyter<span>brand.degruyter.com</span></div>
<div class="dg-intro-text">
The De Gruyter brand palette is the <strong>source of truth</strong> for all color decisions. Primary is always <strong>black</strong>. 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 <strong>deep navy</strong> (#002850) as the primary interactive color to soften the archival aesthetic while staying within the brand's dark-anchor principle.
</div>
</div>
<h3 class="sub-title">De Gruyter Primary</h3>
<div class="swatch-grid" style="grid-template-columns:repeat(auto-fill,minmax(160px,1fr))">
<div class="swatch">
<div class="swatch-color" style="background:#000000"></div>
<div class="swatch-info">
<div class="swatch-name">Black — Primary</div>
<div class="swatch-hex">#000000</div>
<div class="swatch-rule">Dominates all layouts. Logo, headline type, layout anchoring. Always present.</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#FFFFFF;border-bottom:1px solid #E8E4DF"></div>
<div class="swatch-info">
<div class="swatch-name">White</div>
<div class="swatch-hex">#FFFFFF</div>
<div class="swatch-rule">Surfaces, cards, form fields. White logo on dark backgrounds.</div>
</div>
</div>
</div>
<h3 class="sub-title">De Gruyter Secondary Colors</h3>
<p class="desc">Use each secondary color only with black — never combine two secondary colors together. Never use white text on Yellow-Green or Mustard.</p>
<div class="swatch-grid">
<div class="swatch">
<div class="swatch-color" style="background:#8A8B1D"></div>
<div class="swatch-info">
<div class="swatch-name">Yellow-Green</div>
<div class="swatch-hex">#8A8B1D · PMS 384</div>
<div class="swatch-rule">⚠ Use BLACK text only. White fails contrast.</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#8C7E5E"></div>
<div class="swatch-info">
<div class="swatch-name">Muted Brown</div>
<div class="swatch-hex">#8C7E5E · PMS 2325</div>
<div class="swatch-rule">Warm neutrals, archival accents.</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#CACAC9;border-bottom:1px solid #E8E4DF"></div>
<div class="swatch-info">
<div class="swatch-name">Silver</div>
<div class="swatch-hex">#CACAC9 · PMS 420</div>
<div class="swatch-rule">Decorative only. Never as text on white — fails contrast.</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#007596"></div>
<div class="swatch-info">
<div class="swatch-name">Blue-Green</div>
<div class="swatch-hex">#007596 · PMS 7705</div>
<div class="swatch-rule">5.3:1 on white → WCAG AA ✓ White text on this color.</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#A81266"></div>
<div class="swatch-info">
<div class="swatch-name">Magenta</div>
<div class="swatch-hex">#A81266 · PMS 234</div>
<div class="swatch-rule">6.8:1 on white → WCAG AA ✓</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#615B66"></div>
<div class="swatch-info">
<div class="swatch-name">Granite Gray</div>
<div class="swatch-hex">#615B66 · PMS 2363</div>
<div class="swatch-rule">Secondary body text on white only.</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#AF860E"></div>
<div class="swatch-info">
<div class="swatch-name">Mustard</div>
<div class="swatch-hex">#AF860E · PMS 1245</div>
<div class="swatch-rule">⚠ Use BLACK text only. Warning states.</div>
</div>
</div>
</div>
<h3 class="sub-title">De Gruyter Accent Colors</h3>
<p class="desc">Accent colors are used only in combination with black. Never combine two accent colors — exception: data visualizations with a defined key.</p>
<div class="swatch-grid">
<div class="swatch">
<div class="swatch-color" style="background:#00C7B1"></div>
<div class="swatch-info"><div class="swatch-name">Turquoise</div><div class="swatch-hex">#00C7B1</div></div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#FFB81C"></div>
<div class="swatch-info">
<div class="swatch-name">Gold</div>
<div class="swatch-hex">#FFB81C</div>
<div class="swatch-rule">9.1:1 on black → WCAG AAA ✓</div>
</div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#BF4DA5"></div>
<div class="swatch-info"><div class="swatch-name">Lavender</div><div class="swatch-hex">#BF4DA5</div></div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#008AD8"></div>
<div class="swatch-info"><div class="swatch-name">Blue</div><div class="swatch-hex">#008AD8</div></div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#F18070"></div>
<div class="swatch-info"><div class="swatch-name">Rose</div><div class="swatch-hex">#F18070</div></div>
</div>
<div class="swatch">
<div class="swatch-color" style="background:#F18700"></div>
<div class="swatch-info">
<div class="swatch-name">OA Orange</div>
<div class="swatch-hex">#F18700</div>
<div class="swatch-rule">Open Access only. Not for general UI.</div>
</div>
</div>
</div>
<hr class="rule">
<h3 class="sub-title">Familienarchiv Application Tokens</h3>
<p class="desc">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.</p>
<table class="token-table">
<thead>
<tr>
<th>Token</th>
<th>Value</th>
<th>Preview</th>
<th>Usage</th>
</tr>
</thead>
<tbody>
<tr>
<td>--brand-navy</td>
<td>#002850</td>
<td><span class="dot-preview" style="background:#002850"></span></td>
<td>Primary interactive color: buttons, active states, key headings, links. Replaces De Gruyter black in UI chrome.</td>
</tr>
<tr>
<td>--brand-nav</td>
<td>#0D2240</td>
<td><span class="dot-preview" style="background:#0D2240"></span></td>
<td>Navigation bar, sidebars, entity panels. Slightly darker than navy.</td>
</tr>
<tr>
<td>--brand-mint</td>
<td>#A6DAD8</td>
<td><span class="dot-preview" style="background:#A6DAD8"></span></td>
<td>Active state underlines, accent borders, hover highlights. Never as standalone text.</td>
</tr>
<tr>
<td>--brand-sand</td>
<td>#ECEAE4</td>
<td><span class="dot-preview" style="background:#ECEAE4"></span></td>
<td>Page background. Warm parchment. The breathing room of the layout.</td>
</tr>
<tr>
<td>--surface</td>
<td>#FFFFFF</td>
<td><span class="dot-preview" style="background:#FFFFFF;border:1px solid #E5E7EB"></span></td>
<td>Cards, detail panels, form fields, any white surface content lives on.</td>
</tr>
<tr>
<td>--surface-alt</td>
<td>#F7F5F2</td>
<td><span class="dot-preview" style="background:#F7F5F2"></span></td>
<td>List panel backgrounds, panel headers, table row alt. One step warmer than white.</td>
</tr>
<tr>
<td>--surface-hover</td>
<td>#F0EDE8</td>
<td><span class="dot-preview" style="background:#F0EDE8"></span></td>
<td>Hover state on list items, panel headers.</td>
</tr>
<tr>
<td>--border</td>
<td>#E8E4DF</td>
<td><span class="dot-preview" style="background:#E8E4DF"></span></td>
<td>Default card and form borders. Warm, not cold gray.</td>
</tr>
<tr>
<td>--border-strong</td>
<td>#C8C4BE</td>
<td><span class="dot-preview" style="background:#C8C4BE"></span></td>
<td>Section dividers, masthead underlines. Stronger visual separation.</td>
</tr>
<tr>
<td>--text-primary</td>
<td>#1A1A1A</td>
<td><span class="dot-preview" style="background:#1A1A1A"></span></td>
<td>Body text, list item names. Near-black — softer than pure #000.</td>
</tr>
<tr>
<td>--text-secondary</td>
<td>#555555</td>
<td><span class="dot-preview" style="background:#555555"></span></td>
<td>Secondary descriptors, taglines, form hints.</td>
</tr>
<tr>
<td>--text-muted</td>
<td>#888888</td>
<td><span class="dot-preview" style="background:#888888"></span></td>
<td>Labels, metadata, section headers inside cards. 4.5:1 on white → AA ✓</td>
</tr>
<tr>
<td>--text-xmuted</td>
<td>#AAAAAA</td>
<td><span class="dot-preview" style="background:#AAAAAA"></span></td>
<td>Decorative only — placeholder text, empty state icons. Never for readable content.</td>
</tr>
<tr>
<td>--danger</td>
<td>#DC2626</td>
<td><span class="dot-preview" style="background:#DC2626"></span></td>
<td>Destructive actions, error states, required field markers.</td>
</tr>
<tr>
<td>--warning</td>
<td>#D97706</td>
<td><span class="dot-preview" style="background:#D97706"></span></td>
<td>Warning banners, unsaved state indicators. Black text on this background.</td>
</tr>
<tr>
<td>--success</td>
<td>#15803D</td>
<td><span class="dot-preview" style="background:#15803D"></span></td>
<td>Success states, import completion, positive confirmations.</td>
</tr>
</tbody>
</table>
<h3 class="sub-title">Contrast Reference</h3>
<p class="desc">All text combinations must pass WCAG AA. Key pairs used in the app:</p>
<div style="background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:4px 0;margin-bottom:24px">
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#002850;color:#fff">Button</div>
<div class="contrast-ratio">14.7:1</div>
<span class="contrast-status pass-aaa">AAA</span>
<div class="contrast-desc">#FFFFFF on #002850 — primary button, nav active</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#0D2240;color:#fff">Nav</div>
<div class="contrast-ratio">16.1:1</div>
<span class="contrast-status pass-aaa">AAA</span>
<div class="contrast-desc">#FFFFFF on #0D2240 — navbar, sidebar</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#fff;color:#1A1A1A">Body</div>
<div class="contrast-ratio">18.1:1</div>
<span class="contrast-status pass-aaa">AAA</span>
<div class="contrast-desc">#1A1A1A on #FFFFFF — body text on cards</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#ECEAE4;color:#1A1A1A">Page</div>
<div class="contrast-ratio">16.4:1</div>
<span class="contrast-status pass-aaa">AAA</span>
<div class="contrast-desc">#1A1A1A on #ECEAE4 — text on sand background</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#fff;color:#888">Label</div>
<div class="contrast-ratio">4.5:1</div>
<span class="contrast-status pass-aa">AA</span>
<div class="contrast-desc">#888888 on #FFFFFF — section labels, metadata. Minimum passing.</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#fff;color:#AAA">Muted</div>
<div class="contrast-ratio">2.3:1</div>
<span class="contrast-status fail-c">FAIL</span>
<div class="contrast-desc">#AAAAAA on #FFFFFF — decorative only, never for real text</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#007596;color:#fff">DG</div>
<div class="contrast-ratio">5.3:1</div>
<span class="contrast-status pass-aa">AA</span>
<div class="contrast-desc">White on DG Blue-Green — use white text on this</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#8A8B1D;color:#fff"></div>
<div class="contrast-ratio">2.1:1</div>
<span class="contrast-status fail-c">FAIL</span>
<div class="contrast-desc">DG Yellow-Green with white text — always use black text on this</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#8A8B1D;color:#000">OK</div>
<div class="contrast-ratio">8.6:1</div>
<span class="contrast-status pass-aaa">AAA</span>
<div class="contrast-desc">DG Yellow-Green with black text ✓</div>
</div>
<div class="contrast-row" style="padding:10px 16px">
<div class="contrast-chip" style="background:#CACAC9;color:#fff"></div>
<div class="contrast-ratio">1.6:1</div>
<span class="contrast-status fail-c">FAIL</span>
<div class="contrast-desc">DG Silver — decorative only, never as text color on white</div>
</div>
</div>
<!-- Dark mode tokens -->
<h3 class="sub-title">Dark Mode Tokens</h3>
<p class="desc">Dark mode is not a color inversion. It remaps tokens intentionally across the navy spectrum. The archival warmth is preserved through warm dark backgrounds.</p>
<table class="token-table">
<thead><tr><th>Token</th><th>Light value</th><th>Dark value</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>--bg-page</td><td>#ECEAE4</td><td>#0A1628</td><td>Deep navy — not pure black</td></tr>
<tr><td>--bg-surface</td><td>#FFFFFF</td><td>#0F1E35</td><td>Cards, panels</td></tr>
<tr><td>--bg-surface-alt</td><td>#F7F5F2</td><td>#162236</td><td>List panels, alt rows</td></tr>
<tr><td>--bg-nav</td><td>#0D2240</td><td>#050E1A</td><td>Darker for nav in dark mode</td></tr>
<tr><td>--border</td><td>#E8E4DF</td><td>#1E3352</td><td></td></tr>
<tr><td>--border-strong</td><td>#C8C4BE</td><td>#2A4570</td><td></td></tr>
<tr><td>--text-primary</td><td>#1A1A1A</td><td>#E8E6E1</td><td>Warm white, not #FFF</td></tr>
<tr><td>--text-secondary</td><td>#555555</td><td>#A8B4C4</td><td></td></tr>
<tr><td>--text-muted</td><td>#888888</td><td>#6B7E96</td><td>Must pass 4.5:1 on dark bg</td></tr>
<tr><td>--brand-navy (interactive)</td><td>#002850</td><td>#4A8FD4</td><td>Lightened so links are visible</td></tr>
<tr><td>--brand-mint</td><td>#A6DAD8</td><td>#7DC4C0</td><td>Slightly desaturated for dark</td></tr>
</tbody>
</table>
<div class="do-dont">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Define all colors as CSS custom properties — never hardcode hex values in components</div>
<div class="rule-item do-item">Map light → dark tokens semantically (<code>--bg-surface</code> not <code>--white</code>)</div>
<div class="rule-item do-item">Use black text on De Gruyter Yellow-Green and Mustard backgrounds</div>
<div class="rule-item do-item">Use white text on --brand-navy and --brand-nav backgrounds</div>
<div class="rule-item do-item">Keep <code>--text-muted</code> (#888) as the minimum for readable labels</div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Use De Gruyter Silver (#CACAC9) as a text color on white</div>
<div class="rule-item dont-item">Combine two De Gruyter secondary or accent colors in the same element</div>
<div class="rule-item dont-item">Implement dark mode by simply inverting the light palette</div>
<div class="rule-item dont-item">Use <code>--text-xmuted</code> (#AAA) for any text that carries meaning</div>
<div class="rule-item dont-item">Rely on color alone to convey state (always pair with icon or label)</div>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 3 · TYPOGRAPHY -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">3 · Typography</h2>
<div class="callout">
<div class="callout-title">Two-font system</div>
<p><strong>Montserrat (sans-serif)</strong> — UI chrome: labels, buttons, metadata, navigation. Mirrors De Gruyter's Gotham: modern, legible, uppercase for headings.</p>
<p><strong>Merriweather (serif)</strong> — Content: person names, document titles, page headings, quoted text. Mirrors De Gruyter's Times: warm, authoritative, human.</p>
</div>
<h3 class="sub-title">Type Scale</h3>
<div class="type-specimen">
<div class="type-meta">Display · 32px · weight 900 · letter-spacing -1px · Montserrat</div>
<div style="font-size:32px;font-weight:900;color:#0D2240;letter-spacing:-1px">Familienarchiv</div>
<div class="type-label">Masthead, hero headings, marketing copy</div>
</div>
<div class="type-specimen">
<div class="type-meta">Page title · 24px · weight 800 · Merriweather</div>
<div style="font-size:24px;font-weight:800;color:#0D2240;font-family:Georgia,serif">Personen-Verzeichnis</div>
<div class="type-label">Page H1, panel headings, person names in detail views</div>
</div>
<div class="type-specimen">
<div class="type-meta">Section title · 20px · weight 800 · Montserrat</div>
<div style="font-size:20px;font-weight:800;color:#002850">Admin — Benutzer &amp; Gruppen</div>
<div class="type-label">Section headings, card titles in admin</div>
</div>
<div class="type-specimen">
<div class="type-meta">Body · 16px · weight 400 · line-height 1.7 · Merriweather</div>
<div style="font-size:16px;font-family:Georgia,serif;line-height:1.7;color:#1A1A1A;max-width:600px">
Die Familie Raddatz lebte von 1887 bis 1943 in Breslau. Diese Sammlung enthält über 240 digitalisierte Briefe, Urkunden und Fotografien aus dem Familienbesitz.
</div>
<div class="type-label">Document summaries, notes fields, any long-form content. Minimum 16px — never smaller.</div>
</div>
<div class="type-specimen">
<div class="type-meta">UI body · 14px · weight 400 · Montserrat</div>
<div style="font-size:14px;color:#555;line-height:1.6">47 Dokumente · Zuletzt bearbeitet 12. März 2026 · Status: Archiviert</div>
<div class="type-label">Table cells, list item metadata, form descriptions</div>
</div>
<div class="type-specimen">
<div class="type-meta">Label · 11px · weight 800 · uppercase · tracking 2px · Montserrat</div>
<div style="font-size:11px;font-weight:800;color:#888;text-transform:uppercase;letter-spacing:2px">Absender · Empfänger · Dokumentenstatus</div>
<div class="type-label">Form labels, card section headers, table column headers. This is the visual workhorse of the UI chrome.</div>
</div>
<div class="type-specimen">
<div class="type-meta">Caption · 12px · weight 400 · Montserrat</div>
<div style="font-size:12px;color:#888">Hochgeladen am 5. März 2026 um 14:32 Uhr</div>
<div class="type-label">Timestamps, file info, captions. Never below 12px.</div>
</div>
<div class="type-specimen" style="background:#0D2240">
<div class="type-meta" style="color:rgba(255,255,255,.4)">Nav link · 10px · weight 700 · uppercase · Montserrat · on dark</div>
<div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:rgba(255,255,255,.55);display:inline-block;margin-right:16px">Dokumente</div>
<div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:#fff;border-bottom:2px solid #A6DAD8;padding-bottom:2px;display:inline-block">Personen</div>
<div class="type-label" style="color:rgba(255,255,255,.3)">Inactive vs. active nav link. Active gets mint underline, not bold weight change.</div>
</div>
<h3 class="sub-title">De Gruyter Typography Mapping</h3>
<table class="token-table">
<thead><tr><th>De Gruyter role</th><th>DG font</th><th>App equivalent</th><th>Usage context</th></tr></thead>
<tbody>
<tr><td>Headings</td><td>Gotham Bold, ALL CAPS</td><td>Montserrat 800, uppercase</td><td>Section labels, navigation, buttons</td></tr>
<tr><td>Intro text</td><td>Gotham Book</td><td>Montserrat 400</td><td>UI metadata, captions, descriptions</td></tr>
<tr><td>Body copy</td><td>Times Regular</td><td>Merriweather Regular</td><td>Document content, names, page titles</td></tr>
<tr><td>Captions/footnotes</td><td>Gotham Book small</td><td>Montserrat 400 12px</td><td>Timestamps, file info</td></tr>
<tr><td>Quotes</td><td>Times LT Italic/Semibold</td><td>Merriweather Italic</td><td>Quoted document passages</td></tr>
</tbody>
</table>
<div class="do-dont">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Use serif (Merriweather) for person names, document titles, page H1s</div>
<div class="rule-item do-item">Use sans-serif (Montserrat) uppercase for all form labels and section headers</div>
<div class="rule-item do-item">Minimum 16px for body text, minimum 12px for any visible text</div>
<div class="rule-item do-item">Line-height 1.61.7 for body copy, 1.4 for compact UI text</div>
<div class="rule-item do-item">Use <code>font-family: Georgia, serif</code> as fallback until Merriweather loads</div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Mix serif and sans-serif within a single label or button</div>
<div class="rule-item dont-item">Set any visible text below 12px — use abbreviation, truncation, or tooltip instead</div>
<div class="rule-item dont-item">Use uppercase for body text — only for labels and navigation</div>
<div class="rule-item dont-item">Use font-weight 900 for anything other than masthead or hero display text</div>
<div class="rule-item dont-item">Rely on font-weight alone to distinguish hierarchy — pair with size change</div>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 4 · RESPONSIVE BREAKPOINTS -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">4 · Responsive Breakpoints</h2>
<p class="desc">Design mobile-first. Desktop is an enhancement, not the baseline. Every layout decision starts at 375px and scales up.</p>
<div class="bp-grid">
<div class="bp-card">
<div class="bp-header">
<span class="bp-label">📱 Mobile</span>
<span class="bp-px">≤ 639px</span>
</div>
<div class="bp-body">
<div class="bp-rule">Navigation</div>
<p>Hamburger menu or bottom tab bar. Nav items collapse — logo + hamburger icon only in the top bar.</p>
<div class="bp-rule">Lists</div>
<p>1-column. Full-width cards stacked vertically.</p>
<div class="bp-rule">Detail views</div>
<p>Single column. Sidebar pushes below content. Sticky save bar at bottom of viewport.</p>
<div class="bp-rule">Admin / master-detail</div>
<p>Push navigation: list view → push to detail. No side-by-side panels.</p>
<div class="bp-rule">Touch targets</div>
<p>Minimum 44×44px. Prefer 48×48px. Primary actions in the thumb zone (bottom 2/3 of screen).</p>
<div class="bp-rule">Filter panels</div>
<p>Full-screen overlay. Opened via "Filter" button, dismissed with "Anwenden".</p>
</div>
</div>
<div class="bp-card">
<div class="bp-header">
<span class="bp-label">📱 Tablet</span>
<span class="bp-px">6401023px</span>
</div>
<div class="bp-body">
<div class="bp-rule">Navigation</div>
<p>Full top navbar visible. Entity nav sidebar collapses to 48px icon strip with tooltip on hover.</p>
<div class="bp-rule">Lists</div>
<p>2-column grids. Person cards in 2 columns.</p>
<div class="bp-rule">Detail views</div>
<p>Single column stacked (same as mobile). Sidebar below content.</p>
<div class="bp-rule">Admin / master-detail</div>
<p>List panel collapsible: 240px expanded ↔ 32px collapsed handle. Detail panel fills remaining space.</p>
<div class="bp-rule">Filter panels</div>
<p>Collapsible inline strip (collapsed) or full filter panel (expanded). Strip shows active filter summary.</p>
<div class="bp-rule">Forms</div>
<p>Full-page form. Two-column field rows acceptable where fields are short (e.g., birth/death dates).</p>
</div>
</div>
<div class="bp-card">
<div class="bp-header">
<span class="bp-label">🖥 Desktop</span>
<span class="bp-px">≥ 1024px</span>
</div>
<div class="bp-body">
<div class="bp-rule">Navigation</div>
<p>Full top navbar + 120px entity nav sidebar (full labels + counts visible).</p>
<div class="bp-rule">Lists</div>
<p>4-column grids for person/document cards. Dense list views with inline actions.</p>
<div class="bp-rule">Detail views</div>
<p>2-column sidebar (35%) + main content (65%). Person card + activity area side by side.</p>
<div class="bp-rule">Admin / master-detail</div>
<p>3 persistent panels: Entity Nav (120px) + List Panel (240px) + Detail Panel (remaining). All visible simultaneously.</p>
<div class="bp-rule">Filter panels</div>
<p>Inline collapsed strip by default. Expands to a full filter card above the list.</p>
<div class="bp-rule">Max content width</div>
<p>1560px. Content always centered. Padding: 48px vertical, 32px horizontal.</p>
</div>
</div>
</div>
<h3 class="sub-title">Layout Anatomy — Desktop Admin (1440px)</h3>
<div style="background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;overflow:hidden;margin-bottom:24px">
<!-- Nav bar -->
<div style="height:44px;background:#0D2240;display:flex;align-items:center;padding:0 18px;gap:14px">
<span style="font-size:11px;font-weight:900;color:#fff;letter-spacing:1px">FAMILIENARCHIV</span>
<span style="font-size:10px;color:rgba(255,255,255,.5);font-weight:700;text-transform:uppercase;letter-spacing:.5px">Dokumente</span>
<span style="font-size:10px;color:rgba(255,255,255,.5);font-weight:700;text-transform:uppercase;letter-spacing:.5px">Personen</span>
<span style="font-size:10px;color:#fff;font-weight:700;text-transform:uppercase;letter-spacing:.5px;border-bottom:2px solid #A6DAD8;padding-bottom:2px">Admin</span>
<span style="margin-left:auto;font-size:10px;color:rgba(255,255,255,.5)">M. Raddatz</span>
</div>
<!-- Three-panel body -->
<div style="display:flex;height:200px">
<!-- Entity nav -->
<div style="width:120px;background:#0D2240;flex-shrink:0;display:flex;flex-direction:column;padding-top:8px">
<div style="padding:8px 12px;font-size:8px;font-weight:800;color:rgba(255,255,255,.3);text-transform:uppercase;letter-spacing:1px">Entitäten</div>
<div style="padding:10px 14px;border-left:3px solid #A6DAD8;background:rgba(255,255,255,.1)">
<div style="font-size:9px;font-weight:800;color:#fff;text-transform:uppercase;letter-spacing:.5px">Benutzer</div>
<div style="font-size:13px;font-weight:900;color:rgba(255,255,255,.65);margin-top:1px">12</div>
</div>
<div style="padding:10px 14px;border-left:3px solid transparent">
<div style="font-size:9px;font-weight:800;color:rgba(255,255,255,.55);text-transform:uppercase;letter-spacing:.5px">Gruppen</div>
<div style="font-size:13px;font-weight:900;color:rgba(255,255,255,.2);margin-top:1px">4</div>
</div>
<div style="padding:10px 14px;border-left:3px solid transparent">
<div style="font-size:9px;font-weight:800;color:rgba(255,255,255,.55);text-transform:uppercase;letter-spacing:.5px">Tags</div>
<div style="font-size:13px;font-weight:900;color:rgba(255,255,255,.2);margin-top:1px">38</div>
</div>
</div>
<!-- List panel -->
<div style="width:240px;flex-shrink:0;background:#F7F5F2;border-right:1px solid #E0DDD6;display:flex;flex-direction:column">
<div style="padding:10px 14px;border-bottom:1px solid #E0DDD6;background:#F0EDE8">
<div style="font-size:10px;font-weight:800;color:#0D2240;text-transform:uppercase;letter-spacing:.5px">Benutzer</div>
</div>
<div style="padding:8px 10px">
<div style="height:26px;border:1.5px solid #D1D5DB;border-radius:5px;background:#fff;display:flex;align-items:center;padding:0 8px;font-size:11px;color:#AAA;font-style:italic">Suche…</div>
</div>
<div style="padding:8px 14px;border-bottom:1px solid #EAE7E2;background:#EEF2FF;border-right:3px solid #002850;display:flex;justify-content:space-between">
<span style="font-size:11px;font-weight:700;color:#002850">Anna Raddatz</span>
<span style="font-size:11px;color:#CCC"></span>
</div>
<div style="padding:8px 14px;border-bottom:1px solid #EAE7E2;display:flex;justify-content:space-between">
<span style="font-size:11px;font-weight:700;color:#1A1A1A">Bernd Schiller</span>
<span style="font-size:11px;color:#CCC"></span>
</div>
<div style="padding:8px 14px;border-bottom:1px solid #EAE7E2;display:flex;justify-content:space-between">
<span style="font-size:11px;font-weight:700;color:#1A1A1A">Claudia Werner</span>
<span style="font-size:11px;color:#CCC"></span>
</div>
</div>
<!-- Detail panel -->
<div style="flex:1;background:#fff;display:flex;flex-direction:column">
<div style="padding:12px 18px;border-bottom:1px solid #E8E4DF;background:#F7F5F2;display:flex;align-items:center;justify-content:space-between">
<div>
<div style="font-size:13px;font-weight:800;color:#0D2240">Anna Raddatz</div>
<div style="font-size:10px;color:#888;margin-top:1px">anna@example.com · Mitglied seit 2024</div>
</div>
<div style="display:flex;gap:8px">
<div style="font-size:10px;font-weight:800;padding:5px 10px;border-radius:4px;border:1.5px solid #002850;color:#002850;background:transparent;text-transform:uppercase">Bearbeiten</div>
</div>
</div>
<div style="padding:16px 18px;flex:1;font-size:12px;color:#888;display:flex;align-items:center;justify-content:center">Detail-Inhalt hier</div>
</div>
</div>
</div>
<div class="do-dont">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Start every layout at 375px viewport width before designing desktop</div>
<div class="rule-item do-item">Use CSS Grid and <code>minmax()</code> for responsive columns — no fixed-pixel column widths</div>
<div class="rule-item do-item">Test at 320px, 375px, 640px, 768px, 1024px, 1440px</div>
<div class="rule-item do-item">Keep the meta viewport tag: <code>&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;</code></div>
<div class="rule-item do-item">Use <code>min-height: 44px</code> on all tappable elements</div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Set fixed pixel widths on layout columns below 1024px</div>
<div class="rule-item dont-item">Show three-panel master-detail layout at 768px — use collapsible list panel</div>
<div class="rule-item dont-item">Design desktop-first and then "shrink down" — information gets lost</div>
<div class="rule-item dont-item">Hide content that exists on desktop from mobile — stack it instead</div>
<div class="rule-item dont-item">Use hover-only interactions as the primary way to discover actions</div>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 5 · COMPONENTS -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">5 · Components</h2>
<!-- 5.1 Navigation -->
<h3 class="sub-title">5.1 · Navigation Bar</h3>
<div class="preview-box">
<div class="nav-preview">
<span class="nav-logo">FAMILIENARCHIV</span>
<span class="nav-link">Dokumente</span>
<span class="nav-link active">Personen</span>
<span class="nav-link">Gespräche</span>
<span class="nav-link">Admin</span>
<div class="nav-right">
<span class="nav-user">M. Raddatz</span>
<div class="nav-icon"></div>
</div>
</div>
<p style="font-size:12px;color:#888">Height: 44px · Background: #0D2240 · Active link: white + 2px #A6DAD8 underline · Inactive link: rgba(255,255,255,.5)</p>
</div>
<div class="do-dont">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Mark active page with white text + 2px mint bottom border</div>
<div class="rule-item do-item">Keep logo text always white and at left edge</div>
<div class="rule-item do-item">Ensure all nav links have visible focus ring (test with keyboard)</div>
<div class="rule-item do-item">Add <code>aria-current="page"</code> to the active nav link</div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Remove focus outline from nav links without a custom focus style</div>
<div class="rule-item dont-item">Use color alone to indicate the active page</div>
<div class="rule-item dont-item">Collapse the navbar to a hamburger on desktop widths</div>
<div class="rule-item dont-item">Put more than 5 top-level nav items in the navbar</div>
</div>
</div>
</div>
<!-- 5.2 Buttons -->
<h3 class="sub-title">5.2 · Buttons</h3>
<div class="preview-box light">
<div class="btn-row">
<button class="btn btn-primary">Speichern</button>
<button class="btn btn-outline">Abbrechen</button>
<button class="btn btn-ghost">Zurück</button>
<button class="btn btn-danger">Löschen</button>
<button class="btn btn-danger-fill">Endgültig löschen</button>
</div>
<div class="btn-row">
<button class="btn btn-primary btn-sm">Hinzufügen</button>
<button class="btn btn-outline btn-sm">Bearbeiten</button>
<button class="btn btn-primary btn-disabled" disabled>Gespeichert</button>
<button class="btn btn-focus-example" style="outline:3px solid rgba(0,40,80,.4)">Fokus-Beispiel</button>
</div>
<p style="font-size:12px;color:#888;margin-top:8px">Sizes: default (40px height) · small (32px) · All uppercase · font-weight 700 · letter-spacing .5px</p>
<p style="font-size:12px;color:#888">Focus ring: <code>outline: 3px solid rgba(0,40,80,.4); outline-offset: 2px</code> — never remove without replacement</p>
</div>
<div class="do-dont">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Use btn-primary for the single most important action per screen</div>
<div class="rule-item do-item">Place destructive actions (btn-danger) away from primary actions — space them</div>
<div class="rule-item do-item">Always include a visible focus ring — use rgba navy shadow, not browser default</div>
<div class="rule-item do-item">Minimum button height 40px (desktop), 44px (mobile / touch)</div>
<div class="rule-item do-item">Add <code>aria-label</code> to icon-only buttons: <code>&lt;button aria-label="Löschen"&gt;</code></div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Use <code>outline: none</code> or <code>outline: 0</code> without a custom focus replacement</div>
<div class="rule-item dont-item">Place two primary buttons next to each other</div>
<div class="rule-item dont-item">Use btn-danger-fill for anything other than a final irreversible action</div>
<div class="rule-item dont-item">Make button text all lowercase — all buttons are uppercase in this system</div>
<div class="rule-item dont-item">Use icon-only buttons without an aria-label or visible tooltip</div>
</div>
</div>
</div>
<!-- 5.3 Cards -->
<h3 class="sub-title">5.3 · Cards</h3>
<div class="preview-box">
<div class="card">
<div class="card-heading">Dokument</div>
<div class="card-title">Brief an Tante Frieda, Weihnachten 1932</div>
<div class="card-sub">Von: Karl Raddatz · An: Frieda Schiller</div>
<div style="display:flex;align-items:center;justify-content:space-between;margin-top:16px">
<div style="display:flex;gap:6px">
<span class="chip chip-mint">Transkribiert</span>
<span class="chip chip-gray">Brief</span>
</div>
<span style="font-size:12px;color:#AAA">25. Dez. 1932</span>
</div>
</div>
<p style="font-size:12px;color:#888">Background: #FFFFFF · Border: 1.5px solid #E8E4DF · border-radius: 8px · padding: 2024px · shadow-sm</p>
</div>
<table class="token-table" style="margin-bottom:24px">
<thead><tr><th>Card variant</th><th>Use case</th><th>Border</th></tr></thead>
<tbody>
<tr><td>Default card</td><td>Content sections, detail panels</td><td><code>1.5px solid #E8E4DF</code></td></tr>
<tr><td>Hover card (list grid)</td><td>Person/doc cards in grid view</td><td><code>1.5px solid #A6DAD8</code> + left accent 3px mint</td></tr>
<tr><td>Selected (master-detail)</td><td>Active list item in panel</td><td><code>border-right: 3px solid #002850</code> + #EEF2FF bg</td></tr>
<tr><td>Warning card</td><td>Pending import, unsaved state</td><td><code>1.5px solid #FDE68A</code> + #FFFBEB bg</td></tr>
<tr><td>Danger zone</td><td>Destructive actions section</td><td><code>1.5px solid #FCA5A5</code> + #FFF5F5 bg</td></tr>
</tbody>
</table>
<!-- 5.4 Forms -->
<h3 class="sub-title">5.4 · Forms</h3>
<div class="preview-box light">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;max-width:600px">
<div class="form-group">
<label class="form-label">Vorname <span class="req">*</span></label>
<input class="form-input" type="text" placeholder="z.B. Karl" style="display:block">
<div class="form-hint">Vollständiger Vorname der Person</div>
</div>
<div class="form-group">
<label class="form-label">Nachname <span class="req">*</span></label>
<input class="form-input error" type="text" value="Raddatz" style="display:block">
<div class="form-error">Dieser Name existiert bereits.</div>
</div>
</div>
<p style="font-size:12px;color:#888;margin-top:16px">Input default: bg #F9FAFB · border #D1D5DB · height 40px · Focus: border #002850 + 3px rgba ring · Error: border #DC2626 + bg #FFF5F5</p>
</div>
<div class="do-dont">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Always use a visible <code>&lt;label&gt;</code> associated with each input via <code>for/id</code></div>
<div class="rule-item do-item">Mark required fields with red asterisk <span style="color:#DC2626">*</span> AND a legend note</div>
<div class="rule-item do-item">Show error text below the field — not in a toast that auto-dismisses</div>
<div class="rule-item do-item">Use the sticky save bar pattern for long forms</div>
<div class="rule-item do-item">Minimum input height 40px (desktop), 44px (mobile)</div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Use placeholder text as the only label — it disappears on focus</div>
<div class="rule-item dont-item">Use red border alone to signal an error — add text explanation</div>
<div class="rule-item dont-item">Auto-dismiss error messages without a manual dismiss option</div>
<div class="rule-item dont-item">Disable the submit button while form is pristine — use server validation instead</div>
<div class="rule-item dont-item">Place more than 3 fields in a horizontal row</div>
</div>
</div>
</div>
<!-- 5.5 Status Chips & Badges -->
<h3 class="sub-title">5.5 · Status Chips &amp; Badges</h3>
<div class="preview-box light">
<div class="chip-row">
<span class="chip chip-navy">Archiviert</span>
<span class="chip chip-mint">Transkribiert</span>
<span class="chip chip-amber">Ausstehend</span>
<span class="chip chip-red">Fehler</span>
<span class="chip chip-green">Hochgeladen</span>
<span class="chip chip-gray">Entwurf</span>
</div>
<!-- Document status dots -->
<div style="margin-top:12px">
<div class="status-row"><div class="status-dot" style="background:#F59E0B"></div>Platzhalter — Datei noch nicht hochgeladen</div>
<div class="status-row"><div class="status-dot" style="background:#22C55E"></div>Hochgeladen</div>
<div class="status-row"><div class="status-dot" style="background:#3B82F6"></div>Transkribiert</div>
<div class="status-row"><div class="status-dot" style="background:#A855F7"></div>Geprüft</div>
<div class="status-row"><div class="status-dot" style="background:#6B7280"></div>Archiviert</div>
</div>
<p style="font-size:12px;color:#888;margin-top:8px">Status dots are always paired with a text label. Never use color alone for document lifecycle state.</p>
</div>
<!-- 5.6 Alerts / Banners -->
<h3 class="sub-title">5.6 · Alerts &amp; Banners</h3>
<div class="preview-box light">
<div class="alert alert-info"><span class="alert-icon"></span><span>Der Import läuft im Hintergrund. Dies kann einige Minuten dauern.</span></div>
<div class="alert alert-warn"><span class="alert-icon"></span><span>Es gibt ungespeicherte Änderungen. Bitte speichern Sie, bevor Sie die Seite verlassen.</span></div>
<div class="alert alert-err"><span class="alert-icon"></span><span>Der Datei-Upload ist fehlgeschlagen. Maximal 50 MB pro Datei erlaubt.</span></div>
<div class="alert alert-ok"><span class="alert-icon"></span><span>15 Dokumente wurden erfolgreich importiert.</span></div>
</div>
<div class="do-dont">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Include an icon + text in every alert (never color-only)</div>
<div class="rule-item do-item">Add <code>role="alert"</code> for error messages, <code>role="status"</code> for info banners</div>
<div class="rule-item do-item">For seniors: persistent banners stay visible until manually dismissed</div>
<div class="rule-item do-item">Place banners above the related content area, not floating over it</div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Auto-dismiss error or warning toasts on a timer</div>
<div class="rule-item dont-item">Stack more than 2 alerts in the same view</div>
<div class="rule-item dont-item">Use generic "An error occurred" — specify what failed and what to do</div>
<div class="rule-item dont-item">Show success alerts for trivial operations (e.g. typing a character)</div>
</div>
</div>
</div>
<!-- 5.7 Empty States -->
<h3 class="sub-title">5.7 · Empty States</h3>
<div class="preview-box">
<div class="empty-state" style="max-width:400px">
<div class="empty-icon">📂</div>
<div class="empty-h">Keine Personen gefunden</div>
<div class="empty-s">Versuchen Sie einen anderen Suchbegriff oder legen Sie eine neue Person an.</div>
<div class="empty-cta">Neue Person anlegen</div>
</div>
<p style="font-size:12px;color:#888;margin-top:12px">Border: 2px dashed #D1CCC8 · bg #F7F5F2 · Icon in 48px circle · Serif heading · CTA button</p>
</div>
<!-- 5.8 Danger Zone -->
<h3 class="sub-title">5.8 · Danger Zone</h3>
<div class="preview-box light">
<div class="danger-zone">
<div class="danger-title">⚠ Gefahrenzone</div>
<div class="danger-desc">Diese Aktionen können nicht rückgängig gemacht werden. Bitte lesen Sie die Beschreibung sorgfältig, bevor Sie fortfahren.</div>
<div class="danger-confirm">
<div class="danger-confirm-msg">Geben Sie zur Bestätigung den Namen "Anna Raddatz" ein:</div>
<div class="form-group" style="margin-bottom:0">
<input class="form-input" type="text" placeholder="Anna Raddatz" style="max-width:280px;border-color:#FCA5A5">
</div>
</div>
<div style="margin-top:12px">
<button class="btn btn-danger-fill btn-sm">Person endgültig löschen</button>
</div>
</div>
<p style="font-size:12px;color:#888;margin-top:8px">Always hidden in a collapsed accordion on load. Require typed confirmation for irreversible delete actions.</p>
</div>
<!-- 5.9 Save Bar -->
<h3 class="sub-title">5.9 · Save Bar</h3>
<div class="preview-box light">
<p style="font-size:12px;color:#555;margin-bottom:12px;font-style:italic">Long forms (edit document, edit person): sticky, full-bleed</p>
<div class="save-bar-sticky" style="border-radius:6px;border:1px solid #E8E4DF">
<span style="font-size:13px;color:#888">Ungespeicherte Änderungen</span>
<div style="display:flex;gap:10px">
<button class="btn btn-outline btn-sm">Abbrechen</button>
<button class="btn btn-primary btn-sm">Speichern</button>
</div>
</div>
<p style="font-size:12px;color:#555;margin-top:20px;margin-bottom:12px;font-style:italic">Short forms (new person, new tag): card-style with top margin</p>
<div class="save-bar" style="margin-top:16px;border-radius:6px;border:1px solid #E8E4DF">
<div></div>
<div style="display:flex;gap:10px">
<button class="btn btn-ghost btn-sm">Abbrechen</button>
<button class="btn btn-primary btn-sm">Person anlegen</button>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 6 · DARK MODE -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">6 · Dark Mode</h2>
<p class="desc">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.</p>
<div class="dark-preview">
<div class="dark-nav">
<span style="font-size:11px;font-weight:900;color:#fff;letter-spacing:1px">FAMILIENARCHIV</span>
<span style="font-size:10px;color:rgba(255,255,255,.45);font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-left:12px">Dokumente</span>
<span style="font-size:10px;color:#fff;font-weight:700;text-transform:uppercase;letter-spacing:.5px;border-bottom:2px solid #7DC4C0;padding-bottom:2px;margin-left:12px">Personen</span>
<span style="margin-left:auto;font-size:10px;color:rgba(255,255,255,.45)">M. Raddatz</span>
</div>
<div class="dark-card">
<div class="dark-card-heading">Dokument</div>
<div class="dark-card-title">Brief an Tante Frieda, Weihnachten 1932</div>
<div class="dark-card-sub">Von: Karl Raddatz · An: Frieda Schiller</div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px">
<div>
<label style="display:block;font-size:11px;font-weight:800;color:#4A6080;text-transform:uppercase;letter-spacing:.5px;margin-bottom:5px">Suchfeld</label>
<input class="dark-input" type="text" placeholder="Suche…" style="display:block">
</div>
<div style="display:flex;align-items:flex-end;gap:8px">
<button class="btn dark-btn-primary" style="background:#3A7CC4;color:#fff;border:none">Suchen</button>
<button class="btn dark-btn-outline" style="border:1.5px solid #3A7CC4;color:#7DB8E8;background:transparent">Filter</button>
</div>
</div>
<p style="font-size:12px;color:#4A6080">Dark mode palette: page bg #0A1628 · surface #0F1E35 · text #E8E6E1 · muted text #6B7E96 · interactive #4A8FD4 · mint #7DC4C0</p>
</div>
<div class="do-dont" style="margin-top:16px">
<div class="do-dont-col">
<div class="do-dont-head do-head">✓ Do</div>
<div class="do-dont-body">
<div class="rule-item do-item">Use <code>prefers-color-scheme: dark</code> as the CSS media query trigger</div>
<div class="rule-item do-item">Lighten interactive colors for dark mode (#4A8FD4 instead of #002850)</div>
<div class="rule-item do-item">Use warm near-white (#E8E6E1) instead of pure white for text on dark</div>
<div class="rule-item do-item">Re-verify every text-background contrast pair in dark mode separately</div>
<div class="rule-item do-item">Keep mint accent (#7DC4C0) for active states — slightly desaturated from light mode</div>
</div>
</div>
<div class="do-dont-col">
<div class="do-dont-head dont-head">✕ Don't</div>
<div class="do-dont-body">
<div class="rule-item dont-item">Simply invert the light mode palette — this breaks the visual hierarchy</div>
<div class="rule-item dont-item">Use pure black (#000) as the dark background — too harsh</div>
<div class="rule-item dont-item">Use the same #002850 navy as interactive color — it disappears on dark bg</div>
<div class="rule-item dont-item">Hardcode colors in components — always use CSS custom properties</div>
<div class="rule-item dont-item">Assume light mode contrast ratios carry over to dark mode</div>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 7 · ACCESSIBILITY (WCAG 2.2) -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">7 · Accessibility — WCAG 2.2</h2>
<div class="callout">
<div class="callout-title">Dual-audience requirement</div>
<p>Familienarchiv serves both <strong>millennials (2542)</strong> and <strong>seniors (60+)</strong>. 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.</p>
</div>
<div class="wcag-grid">
<div class="wcag-card">
<span class="wcag-level wcag-aa">1.4.3 — AA</span>
<div class="wcag-title">Contrast Ratio: Text</div>
<div class="wcag-desc">Normal text (below 18px regular / 14px bold): minimum <strong>4.5:1</strong>. Large text (18px+ regular or 14px+ bold): minimum <strong>3:1</strong>. Body copy target: 7:1 (AAA).</div>
<div class="wcag-example" style="background:#F7F5F2;border-left:3px solid #15803D">
<span style="color:#888;font-size:13px">Label text #888 on white: 4.5:1 ✓</span><br>
<span style="color:#1A1A1A;font-size:13px">Body text #1A1A1A on white: 18.1:1 ✓</span>
</div>
</div>
<div class="wcag-card">
<span class="wcag-level wcag-aa">1.4.11 — AA</span>
<div class="wcag-title">Non-text Contrast</div>
<div class="wcag-desc">UI components (form borders, focus rings, icons) need <strong>3:1</strong> contrast against their background. A #D1D5DB form border on white = 1.9:1 — add focus state immediately.</div>
<div class="wcag-example" style="background:#F7F5F2;border-left:3px solid #D97706">
<span style="font-size:12px;color:#555">Form border #D1D5DB on white: 1.9:1 (fails — acceptable only when focus state at 3:1+ compensates)</span>
</div>
</div>
<div class="wcag-card">
<span class="wcag-level wcag-aa">2.4.7 — AA</span>
<div class="wcag-title">Focus Visible</div>
<div class="wcag-desc">Every interactive element must have a clearly visible focus indicator. Use <code>outline: 3px solid rgba(0,40,80,.4); outline-offset: 2px</code>. Never <code>outline: none</code> without replacement.</div>
<div class="wcag-example" style="background:#F7F5F2;border-left:3px solid #15803D">
<button class="btn btn-focus-example" style="outline:3px solid rgba(0,40,80,.4);outline-offset:2px;font-size:12px;padding:6px 12px">Fokus-Zustand</button>
</div>
</div>
<div class="wcag-card">
<span class="wcag-level wcag-aa">1.3.1 — A</span>
<div class="wcag-title">Info &amp; Relationships</div>
<div class="wcag-desc">Form labels must be programmatically associated with inputs. Section headings must use correct heading elements. Status colors must have text or icon pairing.</div>
<div class="wcag-example" style="background:#FFF5F5;border-left:3px solid #DC2626;font-size:12px;color:#444">
Bad: <code>&lt;div class="label"&gt;</code> + <code>&lt;input&gt;</code><br>
Good: <code>&lt;label for="name"&gt;</code> + <code>&lt;input id="name"&gt;</code>
</div>
</div>
<div class="wcag-card">
<span class="wcag-level wcag-aaa">1.4.6 — AAA (target)</span>
<div class="wcag-title">Enhanced Contrast (Body)</div>
<div class="wcag-desc">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).</div>
</div>
<div class="wcag-card">
<span class="wcag-level wcag-aa">2.5.3 — A</span>
<div class="wcag-title">Label in Name</div>
<div class="wcag-desc">The accessible name of a button must contain its visible text. Icon-only buttons need <code>aria-label</code>. Visible "Speichern" button → <code>aria-label</code> must include "Speichern".</div>
</div>
<div class="wcag-card">
<span class="wcag-level wcag-aa">2.4.3 — A</span>
<div class="wcag-title">Focus Order</div>
<div class="wcag-desc">Tab order must match visual reading order. Modal dialogs trap focus. On mobile, the sticky save bar must be reachable by keyboard. Avoid <code>tabindex</code> values above 0.</div>
</div>
<div class="wcag-card">
<span class="wcag-level wcag-aa">4.1.3 — AA</span>
<div class="wcag-title">Status Messages</div>
<div class="wcag-desc">Dynamically injected alerts must be announced by screen readers without receiving focus. Use <code>role="alert"</code> for errors, <code>role="status"</code> for non-critical updates (import progress).</div>
</div>
</div>
<h3 class="sub-title">Seniors (60+) — Additional Requirements</h3>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px">
<div style="background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:16px 18px">
<div style="font-size:11px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:1px;margin-bottom:10px">Text &amp; Readability</div>
<div class="rule-item do-item" style="font-size:13px">Minimum 16px body text — prefer 18px</div>
<div class="rule-item do-item" style="font-size:13px">Line-height minimum 1.6 for all body copy</div>
<div class="rule-item do-item" style="font-size:13px">Paragraph spacing minimum 0.5em</div>
<div class="rule-item do-item" style="font-size:13px">No text below 12px for any visible content</div>
<div class="rule-item do-item" style="font-size:13px">Avoid italic text for long passages</div>
</div>
<div style="background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:16px 18px">
<div style="font-size:11px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:1px;margin-bottom:10px">Interaction</div>
<div class="rule-item do-item" style="font-size:13px">Touch targets minimum 44×44px, prefer 48px</div>
<div class="rule-item do-item" style="font-size:13px">Persistent primary navigation always visible</div>
<div class="rule-item do-item" style="font-size:13px">No timed interactions or auto-advancing content</div>
<div class="rule-item do-item" style="font-size:13px">Redundant cues: color + icon + text label</div>
<div class="rule-item do-item" style="font-size:13px">Max 3 focal points per screen on mobile</div>
</div>
</div>
<h3 class="sub-title">Semantic HTML Landmarks</h3>
<p class="desc">Every page must contain these landmark elements to enable screen reader navigation:</p>
<div style="background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:0;overflow:hidden;margin-bottom:24px">
<table class="token-table" style="margin-bottom:0">
<thead><tr><th>Element</th><th>Purpose</th><th>Required</th></tr></thead>
<tbody>
<tr><td><code>&lt;header&gt;</code></td><td>Site navigation bar</td><td>✓ Always</td></tr>
<tr><td><code>&lt;nav&gt;</code></td><td>Primary navigation links with <code>aria-label="Hauptnavigation"</code></td><td>✓ Always</td></tr>
<tr><td><code>&lt;main&gt;</code></td><td>Main page content — only one per page</td><td>✓ Always</td></tr>
<tr><td><code>&lt;footer&gt;</code></td><td>Page footer with meta links</td><td>✓ Always</td></tr>
<tr><td><code>&lt;aside&gt;</code></td><td>Sidebar panels (person card, filter panel)</td><td>When sidebar present</td></tr>
<tr><td><code>role="dialog"</code> + <code>aria-modal="true"</code></td><td>Modal overlays (confirm delete)</td><td>When modal present</td></tr>
</tbody>
</table>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 8 · SPACING -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">8 · Spacing &amp; Layout Rhythm</h2>
<p class="desc">Spacing follows a 4px base grid. All values are multiples of 4. Key values in the component system:</p>
<table class="token-table" style="margin-bottom:24px">
<thead><tr><th>Token</th><th>Value</th><th>Usage</th></tr></thead>
<tbody>
<tr><td>--space-1</td><td>4px</td><td>Icon gaps, tight inline spacing</td></tr>
<tr><td>--space-2</td><td>8px</td><td>Chip gaps, input inner padding</td></tr>
<tr><td>--space-3</td><td>12px</td><td>Card inner padding (compact), list item padding</td></tr>
<tr><td>--space-4</td><td>16px</td><td>Form group spacing, section body padding</td></tr>
<tr><td>--space-5</td><td>20px</td><td>Card padding (default), panel padding</td></tr>
<tr><td>--space-6</td><td>24px</td><td>Section gap, grid gap on mobile</td></tr>
<tr><td>--space-8</td><td>32px</td><td>Page horizontal padding, section separation</td></tr>
<tr><td>--space-12</td><td>48px</td><td>Page top/bottom padding, masthead padding</td></tr>
<tr><td>--space-18</td><td>72px</td><td>Section-to-section gap</td></tr>
</tbody>
</table>
<div class="callout">
<div class="callout-title">Panel system</div>
<p><strong>Entity Nav:</strong> 120px (desktop), 48px icon strip (tablet), hidden (mobile). <strong>List Panel:</strong> 240px (desktop), collapsible to 32px handle (tablet), full-screen push (mobile). <strong>Detail Panel:</strong> fills remaining space. Total fixed columns on desktop: 120 + 240 = 360px out of ~1200px viewport.</p>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- 9 · QUICK REFERENCE -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<div class="section">
<h2 class="section-title">9 · Quick Reference</h2>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:20px">
<div style="background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:20px">
<div style="font-size:11px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:1px;margin-bottom:14px">Things you must always do</div>
<div class="rule-item do-item" style="font-size:13px">Visible focus ring on every interactive element</div>
<div class="rule-item do-item" style="font-size:13px">Color + icon/text together for any status indication</div>
<div class="rule-item do-item" style="font-size:13px"><code>&lt;label for&gt;</code> on every form input</div>
<div class="rule-item do-item" style="font-size:13px"><code>aria-label</code> on every icon-only button</div>
<div class="rule-item do-item" style="font-size:13px">Start design at 375px, test at 320px</div>
<div class="rule-item do-item" style="font-size:13px">CSS custom properties for every color value</div>
<div class="rule-item do-item" style="font-size:13px">44px minimum touch target height on mobile</div>
<div class="rule-item do-item" style="font-size:13px">role="alert" on dynamically injected error messages</div>
<div class="rule-item do-item" style="font-size:13px">main, nav, header, footer landmarks on every page</div>
<div class="rule-item do-item" style="font-size:13px">Typed confirmation for irreversible delete actions</div>
</div>
<div style="background:#fff;border:1.5px solid #E8E4DF;border-radius:8px;padding:20px">
<div style="font-size:11px;font-weight:800;color:#AAA;text-transform:uppercase;letter-spacing:1px;margin-bottom:14px">Things you must never do</div>
<div class="rule-item dont-item" style="font-size:13px"><code>outline: none</code> without a custom focus replacement</div>
<div class="rule-item dont-item" style="font-size:13px">Color alone to convey state (error, success, status)</div>
<div class="rule-item dont-item" style="font-size:13px">Text below 12px in production</div>
<div class="rule-item dont-item" style="font-size:13px">Auto-dismiss error or warning toasts</div>
<div class="rule-item dont-item" style="font-size:13px">White text on De Gruyter Yellow-Green (#8A8B1D)</div>
<div class="rule-item dont-item" style="font-size:13px">Silver (#CACAC9) as text color on white</div>
<div class="rule-item dont-item" style="font-size:13px">Combine two De Gruyter secondary colors</div>
<div class="rule-item dont-item" style="font-size:13px">Dark mode as a simple light-mode inversion</div>
<div class="rule-item dont-item" style="font-size:13px">Hardcode hex values in components</div>
<div class="rule-item dont-item" style="font-size:13px">Design desktop-first and shrink to mobile</div>
</div>
</div>
</div>
<!-- Footer -->
<div style="margin-top:80px;padding-top:24px;border-top:2px solid #C8C4BE;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px">
<div style="font-size:11px;color:#AAA;font-weight:600;letter-spacing:1px;text-transform:uppercase">Familienarchiv Style Guide · v1.0 · 2026-03</div>
<div style="font-size:11px;color:#AAA">Leonie Voss · UI/UX Lead · Based on De Gruyter brand guidelines</div>
</div>
</div><!-- /page -->
</body>
</html>