# Familienarchiv — Design Styleguide

This document defines the visual language for the Familienarchiv frontend. All UI work should follow these conventions to stay consistent with the De Gruyter Brill corporate identity.

---

## Brand Identity

The design is based on the **De Gruyter Brill** brand identity (unveiled at Frankfurt Book Fair 2024). Key characteristics:

- Clean white backgrounds, high contrast
- Strong typographic hierarchy (uppercase labels, serif body text)
- Academic publisher aesthetic: authoritative, clear, uncluttered

---

## Colors

Defined in `src/routes/layout.css` as `@theme` variables. All generate Tailwind utilities automatically (`bg-*`, `text-*`, `border-*`).

| Token | Hex | Usage |
|---|---|---|
| `brand-navy` | `#012851` | Primary text, headings, buttons, active states — Prussian Blue |
| `brand-mint` | `#A1DCD8` | Accent color, icon tints, hover underlines — Aqua Island |
| `brand-purple` | `#B4B9FF` | Logo, nav active state highlight, top accent strip — Melrose |
| `brand-sand` | `#F0EFE9` | Subtle card backgrounds, borders, hover backgrounds — paper tone |
| `brand-white` | `#FFFFFF` | Page background, card surfaces |
| `brand-dark` | `#0D0D0D` | Near-black text when maximum contrast is needed |

### Color usage rules

- **Never** use raw hex values in components — always use token utilities.
- Page and card backgrounds are **white**. Use `bg-brand-sand` only for subtle inset areas (e.g. `bg-brand-sand/30`).
- `brand-navy` is the workhorse: headings, body text, borders, primary buttons.
- `brand-mint` is an accent only — never use it as primary text color on white (contrast too low).
- `brand-purple` is reserved for the logo and the single top accent strip in the header.

---

## Typography

### Fonts

| Role | Font | Tailwind | Notes |
|---|---|---|---|
| Body / Serif | **Tinos** (Times substitute) | `font-serif` | Loaded from Google Fonts. Used for document titles, names, body copy, dates. Matches DGB's use of Times. |
| UI / Sans | **Montserrat** (Gotham substitute) | `font-sans` | Loaded from Google Fonts. Used for labels, navigation, buttons, metadata, form elements. Matches DGB's use of Gotham. |

### Type scale and usage

| Element | Classes | Example |
|---|---|---|
| Page title | `font-serif text-3xl text-brand-navy` | `<h1>` |
| Card section heading | `font-sans text-xs font-bold uppercase tracking-widest text-gray-400` | Section labels |
| Document / item title | `font-serif text-xl font-medium text-brand-navy` | List items |
| Metadata / label | `font-sans text-xs font-bold uppercase tracking-widest text-gray-500` | Field labels |
| Body text | `font-serif text-sm text-brand-navy` | Descriptions, summaries |
| Navigation | `font-sans text-xs font-bold uppercase tracking-widest` | Nav links |

### Rules

- **Labels are always uppercase + tracked**: `text-xs font-bold uppercase tracking-widest`
- **Headings** use `font-sans` (Montserrat), set in CSS globally.
- **Content** (document titles, person names, summaries) uses `font-serif` (Tinos).
- Never use `font-serif` for UI chrome (buttons, labels, nav).

---

## Icons

### Library

686 SVG icons in `frontend/static/degruyter-icons/`. Two families:

- **Simple** — single-color, action-oriented. Use for all UI icons. Available in 4 sizes.
- **Complex** — multi-color illustrative icons. Use sparingly for empty states or section headers.

### Simple icon sizes

| Size | Pixels | Path segment | Use |
|---|---|---|---|
| XS | 12px | `X-Small-12px` | Inline text hints, badges |
| SM | 16px | `Small-16px` | Compact UI, table cells |
| **MD** | **24px** | **`Medium-24px`** | **Standard UI icon — default choice** |
| LG | 32px | `Large-32px` | Feature headers, empty states |

### URL pattern

```
/degruyter-icons/Simple/{Size}/SVG/{Category}/{Name}-{Size-Code}.svg
```

**Size codes:** `XS`, `SM`, `MD`, `LG`

### Usage as `<img>` (recommended for static icons)

SVG fills are hardcoded to `#000000`. Use CSS to tint/size them:

```svelte
<!-- Standard icon -->
<img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
     alt="" aria-hidden="true" class="w-6 h-6" />

<!-- Muted/secondary icon -->
<img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
     alt="" aria-hidden="true" class="w-6 h-6 opacity-40" />

<!-- Colored via CSS filter (navy tint) -->
<img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
     alt="" aria-hidden="true"
     class="w-6 h-6"
     style="filter: invert(11%) sepia(58%) saturate(1200%) hue-rotate(192deg) brightness(95%) contrast(101%)" />
```

> **Note:** Always include `alt=""` and `aria-hidden="true"` for decorative icons. For meaningful icons (no visible label next to them), use a descriptive `alt` text instead.

### Key icons for this app

| Use case | Icon path |
|---|---|
| Edit / Bearbeiten | `Action/Edit-Content-MD.svg` |
| Search / Suche | `Action/Mag-Glass-MD.svg` |
| New document | `Action/Add/Add-General-MD.svg` |
| Download | `Action/Download-MD.svg` |
| Upload | `Action/Upload-MD.svg` |
| Filter | `Action/Filter/Filter-Outline-MD.svg` |
| Calendar / date | `Action/Calendar/Calendar-Add-MD.svg` |
| Location | `Action/Location-MD.svg` |
| Person / account | `Action/Account-MD.svg` |
| Chat / conversation | `Action/Chat-MD.svg` |
| Tag / bookmark | `Action/Bookmark/Bookmark-Outline-MD.svg` |
| Close / dismiss | `Action/Close-MD.svg` |
| Back / left arrow | `Action/Arrow/Arrow-Left-MD.svg` |
| Settings / admin | `Action/Settings-MD.svg` |
| Document / PDF | `Action/PDF-Document-MD.svg` |
| Mail | `Action/Mail-MD.svg` |
| Delete | `Action/Remove/Remove-General-MD.svg` |
| Info | `Action/Info/Block/Info-Block-Border-MD.svg` |

---

## Spacing

Based on Tailwind's 4pt grid. Prefer multiples of 4 for all spacing.

| Scale | Value | Use |
|---|---|---|
| `p-1` / `gap-1` | 4px | Tight inline spacing |
| `p-2` | 8px | Small padding (badges, chips) |
| `p-3` | 12px | Compact buttons |
| `p-4` | 16px | Default section padding |
| `p-6` | 24px | Card inner padding (default) |
| `p-8` | 32px | Large card padding |
| `p-10` | 40px | Page vertical padding |
| `gap-6` | 24px | Grid/list gaps |
| `mb-6` | 24px | Standard spacing between sections |
| `mb-10` | 40px | Large spacing between card sections |

---

## Layout

### Page wrapper

All content pages use:
```svelte
<div class="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
```

Narrower pages (forms, detail views):
```svelte
<div class="max-w-4xl mx-auto py-10 px-4">
```

### Header

The global sticky header in `+layout.svelte`:
- Height: **68px** (4px purple accent strip + 64px nav bar)
- Background: `bg-white`
- Bottom border: `border-b border-gray-100`
- Z-index: `z-50`

### Full-screen views

Document detail (`/documents/[id]`) uses a full-viewport split layout:
```svelte
<div class="h-screen flex flex-col bg-white">
  <!-- top bar -->
  <!-- content: sidebar + preview -->
</div>
```

---

## Components

### Card

Standard content card:
```svelte
<div class="bg-white shadow-sm border border-brand-sand rounded-sm p-6">
  <h2 class="text-xs font-bold uppercase tracking-widest text-gray-400 mb-5">
    Section Title
  </h2>
  <!-- content -->
</div>
```

Card with colored accent bar (person/document detail):
```svelte
<div class="bg-white shadow-sm border border-brand-sand rounded-sm overflow-hidden">
  <div class="h-2 bg-brand-navy w-full"></div>
  <div class="p-8 md:p-10">
    <!-- content -->
  </div>
</div>
```

### Buttons

Primary button:
```svelte
<button class="bg-brand-navy text-white px-5 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-brand-navy/90 transition-colors">
  Speichern
</button>
```

Secondary / outline button:
```svelte
<button class="border border-gray-300 text-gray-600 px-5 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-gray-50 transition-colors rounded-sm">
  Abbrechen
</button>
```

Ghost / text button (inline actions):
```svelte
<button class="text-brand-navy/60 hover:text-brand-navy text-sm font-medium font-sans transition-colors">
  Aktion
</button>
```

Destructive button:
```svelte
<button class="border border-red-300 text-red-600 px-4 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-red-50 transition-colors rounded-sm">
  Löschen
</button>
```

Button with DGB icon:
```svelte
<button class="inline-flex items-center gap-2 bg-brand-navy text-white px-4 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-brand-navy/90 transition-colors">
  <img src="/degruyter-icons/Simple/Small-16px/SVG/Action/Edit-Content-SM.svg"
       alt="" aria-hidden="true" class="w-4 h-4 invert" />
  Bearbeiten
</button>
```

> Use `class="invert"` on icons inside dark (navy) buttons to make the black SVG white.

### Form inputs

Label + input pair:
```svelte
<div>
  <label for="field" class="block text-xs font-bold uppercase tracking-widest text-gray-500 mb-1.5 font-sans">
    Feldname *
  </label>
  <input
    id="field" name="field" type="text"
    class="block w-full border border-gray-300 py-2.5 px-3 text-sm font-serif text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
  />
</div>
```

Search input:
```svelte
<div class="relative">
  <input type="text" placeholder="Suchen..."
    class="block w-full border border-gray-300 py-2.5 pr-10 pl-3 font-sans text-sm text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none" />
  <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
    <img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
         alt="" aria-hidden="true" class="w-4 h-4 opacity-40" />
  </div>
</div>
```

### Status badges

```svelte
<!-- Mint (uploaded/active) -->
<span class="inline-flex items-center rounded-full border border-brand-mint/50 bg-brand-mint/20 text-brand-navy px-2.5 py-0.5 text-[10px] font-bold tracking-wide uppercase font-sans">
  UPLOADED
</span>

<!-- Yellow (placeholder/pending) -->
<span class="inline-flex items-center rounded-full border border-yellow-200 bg-yellow-50 text-yellow-700 px-2.5 py-0.5 text-[10px] font-bold tracking-wide uppercase font-sans">
  PLACEHOLDER
</span>
```

### Tag chips

```svelte
<button class="inline-flex items-center rounded bg-brand-sand/30 px-2 py-1 text-[10px] font-bold tracking-widest text-brand-navy uppercase font-sans transition-colors hover:bg-brand-navy hover:text-white">
  Schlagwort
</button>
```

### Back link

```svelte
<a href="/persons" class="inline-flex items-center text-xs font-bold uppercase tracking-widest text-gray-500 hover:text-brand-navy transition-colors group mb-4 font-sans">
  <img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Left-MD.svg"
       alt="" aria-hidden="true"
       class="w-4 h-4 mr-2 opacity-40 group-hover:opacity-100 transition-opacity" />
  Zurück zur Übersicht
</a>
```

### Subtle "new item" link

```svelte
<a href="/documents/new" class="inline-flex items-center gap-1 text-sm font-medium text-brand-navy/60 hover:text-brand-navy transition-colors font-sans">
  <img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Add/Add-General-MD.svg"
       alt="" aria-hidden="true" class="w-4 h-4 opacity-60" />
  Neues Dokument
</a>
```

### Empty state

```svelte
<div class="p-16 text-center">
  <div class="mx-auto mb-4 w-16 h-16 flex items-center justify-center">
    <img src="/degruyter-icons/Simple/Large-32px/SVG/Action/Mag-Glass-LG.svg"
         alt="" aria-hidden="true" class="w-10 h-10 opacity-20" />
  </div>
  <h3 class="font-serif text-lg font-medium text-brand-navy">Keine Dokumente gefunden</h3>
  <p class="mt-1 font-sans text-sm text-gray-500">Versuchen Sie, die Filter anzupassen.</p>
</div>
```

### Nav active state

Current page nav link:
```svelte
class="text-brand-navy bg-brand-purple/15 rounded"
```

Inactive nav link:
```svelte
class="text-gray-500 hover:text-brand-navy hover:bg-brand-sand/60 rounded"
```

Both share the base: `inline-flex items-center px-3 py-1.5 text-xs font-bold uppercase tracking-widest font-sans transition-colors`

### Save bar (long forms)

Sticky full-bleed (document edit):
```svelte
<div class="sticky bottom-0 z-10 -mx-4 px-6 py-4 bg-white border-t border-brand-sand shadow-[0_-2px_8px_rgba(0,0,0,0.06)] flex items-center justify-between">
  <a href="..." class="text-xs font-bold uppercase tracking-widest text-gray-500 hover:text-brand-navy font-sans transition-colors">
    Abbrechen
  </a>
  <button type="submit" class="bg-brand-navy text-white px-6 py-2.5 text-xs font-bold uppercase tracking-widest font-sans hover:bg-brand-navy/90 transition-colors">
    Speichern
  </button>
</div>
```

Card-style (short forms):
```svelte
<div class="mt-4 flex items-center justify-between rounded-sm border border-brand-sand bg-white px-6 py-4 shadow-sm">
```

---

## Do / Don't

| Do | Don't |
|---|---|
| Use `font-sans` for all UI labels, buttons, nav | Use `font-serif` for buttons or labels |
| Use `uppercase tracking-widest` for labels | Use sentence case for field labels |
| Use `brand-navy` for primary actions | Use `brand-mint` as primary action color |
| Use `opacity-*` to create icon tints | Change icon fill color inline |
| Use `invert` class on icons inside `bg-brand-navy` buttons | Use colored icon files for button icons |
| Use `rounded-sm` for cards and buttons (subtle) | Use `rounded-full` for non-pill elements |
| Use `shadow-sm` for card elevation | Use large shadows |
| Keep borders `border-gray-100` or `border-brand-sand` | Use dark borders |
