1404 lines
85 KiB
HTML
1404 lines
85 KiB
HTML
<!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 & 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.6–1.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">640–1023px</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><meta name="viewport" content="width=device-width, initial-scale=1"></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><button aria-label="Löschen"></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: 20–24px · 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><label></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 & 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 & 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 (25–42)</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 & 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><div class="label"></code> + <code><input></code><br>
|
||
Good: <code><label for="name"></code> + <code><input id="name"></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 & 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><header></code></td><td>Site navigation bar</td><td>✓ Always</td></tr>
|
||
<tr><td><code><nav></code></td><td>Primary navigation links with <code>aria-label="Hauptnavigation"</code></td><td>✓ Always</td></tr>
|
||
<tr><td><code><main></code></td><td>Main page content — only one per page</td><td>✓ Always</td></tr>
|
||
<tr><td><code><footer></code></td><td>Page footer with meta links</td><td>✓ Always</td></tr>
|
||
<tr><td><code><aside></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 & 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><label for></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>
|