# Beyonddo Design System

Beyonddo is a **career-navigation platform for the German market** (`de-DE` default, `en` secondary). Its core principle, taken verbatim from the source repository:

> Beyonddo owns the career-navigation journey while connecting users to official German infrastructure and verified partners rather than duplicating BA, mein NOW, Make it in Germany, etc.

The product is a navigation, matching and workflow layer — never a re-implementation of German government infrastructure. The journey it owns:

`Profile → Career goal → Matching → Skill gap → Funding navigation → Training / Job / Ausbildung → Application → Qualification / Employment → Outcome`

## Sources this system was built from

| Source | What was read |
| --- | --- |
| `https://github.com/builtwithcca/beyonddo` (branch `main`) | `README.md` (the V2.2 developer master specification — routes, roles, modules, copy, statuses), `DESIGN.md`, `packages/ui/src/**` (the seven real UI primitives + `tokens.css`), `apps/web/src/**` (the live homepage, locale switcher, system status, German + English message catalogues) |

The reader is encouraged to explore that repository directly — particularly `packages/ui/src/components/` and `apps/web/src/messages/de.json` — before building anything new for this brand. The message catalogues are the single best source of real Beyonddo voice.

**Important context:** the repo's `DESIGN.md` is *deliberately empty*. The original navy / electric-blue palette and screen layouts were cleared so the design could be thought through from scratch rather than reverse-engineered from prescriptions written before the product was understood. Two constraints survived that reset and bind this design system:

1. **WCAG 2.2 AA** — German accessibility law (BFSG) has applied since 28 June 2025. Not a design preference.
2. **No third-party font CDN** — fonts are self-hosted; fetching from Google transmits the visitor's IP without consent (LG München I, 3 O 17493/20).

This design system therefore **keeps the source's structure** (semantic-token discipline, the exact primitive inventory, 44px controls, 8px usage grid, breakpoints, source-provenance vocabulary) and **replaces its hues and type** with the agreed direction: *premium, warm, trust-building*.

## Products / surfaces

| Surface | Route | Status in source |
| --- | --- | --- |
| Public website | `/`, `/chancen`, `/karriere`, `/weiterbildung`, `/jobs`, `/trust`, … | Homepage exists in code; other routes specified, not built |
| Candidate app | `/app`, `/app/career-compass`, `/app/opportunities`, `/app/foerder-navigator`, `/app/wallet` | Specified in detail (fields, statuses, copy rules); layouts not built |
| Employer portal | `/employer/*` | Module list specified only |
| Training-provider portal | `/provider/*` | Module list specified only |
| Admin control centre | `/admin/*` | Navigation tree specified only |

UI kits in this project cover the **public website** and the **candidate app**. Because the source contains no layouts for the app screens, those kits are composed strictly from the specification's own content — its routes, field lists, statuses and German copy — and are labelled as proposals in each kit's README. Nothing is invented beyond layout.

---

## CONTENT FUNDAMENTALS

**Language.** German first, always. `de-DE` is the default locale and English is a translation of it, not the other way round. Write German copy first; if a German sentence only works because you thought in English, rewrite it.

**Person: formal "Sie", always.** This is a product people use when their livelihood is at stake, often alongside a Jobcenter adviser. `Sie`/`Ihr`, never `du`. From the real catalogue: *"Beyonddo begleitet Sie von Ihrer heutigen Situation bis zu einem geprüften nächsten Schritt."* The product speaks about **you** and rarely about itself; "wir" appears only where Beyonddo takes responsibility (verification, privacy).

**Headlines are questions or plain statements of the next step.** Real examples:
- `Was ist Ihr nächster beruflicher Schritt?`
- `Ihr Weg zum nächsten beruflichen Schritt`
- `Der Beyonddo-Weg`

No slogans, no wordplay, no "Unlock your potential". If a headline could belong to a coaching startup, it is wrong.

**Honest modality is a legal requirement, not a tone choice.** The funding navigator may only say things like:
- `Möglicherweise relevant`
- `Möglicher Weg`
- `Lohnt sich zu besprechen`
- `Mit Beratung klären`

Forbidden, in any language: *"Sie haben Anspruch"*, *"genehmigt"*, *"Das Jobcenter zahlt"*, *"You are entitled"*, *"Approved"*. The final decision always belongs to the responsible authority. Likewise: never display fake precision — if the matching model cannot justify a number, do not print a number.

**Provenance is copy, not metadata.** Every opportunity states its origin in words: `Offizielle Quelle`, `Geprüfter Partner`, `Externer Link`, `Lizenzierte Quelle`. External data is never presented as Beyonddo-owned.

**Casing.** Sentence case everywhere — buttons (`Weiterbildung finden`), headings, labels, nav. German nouns capitalise themselves; nothing else does. ALL-CAPS is used only for the eyebrow micro-label (13px, +8% tracking) and never for a full sentence. Never title-case English strings.

**Buttons are verb phrases naming the real action:** `Gesprächsvorbereitung erstellen`, `Mehr erfahren`, `Weiterbildung finden`, `Angebot melden`. Never `Los geht's`, never `Jetzt starten!`.

**Numbers and units.** German conventions: a space before `%` (`70 %`), comma decimal separator, `4 Monate`, `28195`. Percentages and scores render in the mono family so columns align.

**Error and empty states name the cause and the next action.** Real example: *"Die Programmierschnittstelle ist nicht erreichbar / Starten Sie die lokalen Dienste mit „pnpm db:up"."* Note the German typographic quotation marks („…") — use them in German copy.

**Emoji: never.** Not in UI, not in marketing, not in empty states. The source repo contains none, and the audience includes public-sector advisers. Arrows (`→`) are used as flow connectors in the source and are acceptable as decoration, not as meaning-bearing icons.

**Abbreviations spelled out.** The catalogue writes `Programmierschnittstelle` rather than `API` in user-facing German. Prefer the German long form over a borrowed acronym.

**Vibe in one line:** a calm, well-lit public-service counter run by someone who is genuinely competent — warm enough to trust with your CV, precise enough to trust with your funding application.

---

## VISUAL FOUNDATIONS

**Direction.** Premium and warm. Warm charcoal ink on sand and cream grounds, a confident rose primary, generous radii, warm shadows, restrained motion. The reference feel is a modern creative-platform product (per brief) reworked for a German trust context: the warmth and craft, none of the playfulness.

**Colour.**
- *Rose* is the brand primary — one primary action per screen. **Solid fills use `--primary` = `--rose-600 #c53a5c` (5.08:1 on white text), not `--rose-500`:** at 15px/600 the lighter step measures 3.82:1 and fails WCAG 1.4.3. `--rose-500` survives as `--primary-decorative` for non-text uses only (tints, progress fills, the brand ground in `thumbnail.html`), where 3:1 applies. Hover `--rose-700`, press `--rose-800`. Links are `--rose-700`.
- *Ink* is warm charcoal (`--ink-900 #1e1815`), never pure black and never blue-grey.
- *Sand* (`--sand-50 #fdfbf8` → `--sand-600`) is the ground, the borders and the sunken surfaces. Pages are sand; cards are white.
- *Institutional blue* (`--official-500 #2b52b8`) is **reserved for official German infrastructure** — BA, mein NOW, Make it in Germany. It is inherited from the source palette's meaning and must never be used decoratively.
- *Verified green* (`--verified-500`) = Beyonddo-checked partner or document. *Amber* = "may be relevant", external, expiring. *Clay* (`--clay-500`) = destructive/rejected — a warm red, not a fire alarm.
- Colour never carries meaning alone (WCAG 1.4.1): every status also has a word.
- **AA-verified text pairs** (do not reintroduce lighter fills for text): white on `--rose-600` 5.08:1 · white on `--clay-500` 5.92:1 · `--rose-800` on `--rose-50` · `--ink-800` on `--sand-50` · `--ink-500` on `--sand-50` for 13px+ metadata only.
- Maximum two background tones on a page: sand and white, plus at most one inverse ink block.

**Type.** One family — **Mona Sans** (300–800, stack `"Mona Sans", "Helvetica Neue", Helvetica, Arial, sans-serif`) — plus **JetBrains Mono** for anything numeric or technical. Display sizes are deliberately tighter than a conventional scale (`--text-display 64px`, `--text-h1 48px`) so German compounds like *Beratungsvorbereitung* survive one line on tablet. Display weight 800 at −3% tracking; headings 600 at −1.5%; body 19px in-product / 23px marketing at 1.5–1.62 line height; 16px is the absolute floor. Measure caps at 68 characters.

**Spacing & layout.** 4px base step, but the *usage rule* is an 8px grid — prefer even steps. Card padding 24px, block gap 32px, marketing section rhythm 80–112px. Controls are 44px tall (WCAG 2.5.8) — 36px only for dense secondary toolbars. App shell: 264px sidebar, 68px header, 1200px content max; site content 1240px. Breakpoints: 320 base (unprefixed), 768 tablet, 1024 desktop, 1440 large — there is deliberately no `sm` tier. Fixed elements: the app sidebar and top header are sticky; the marketing header is sticky and switches to `--glass-surface` + `--glass-blur` after scroll. Nothing else is fixed — no floating chat bubbles, no sticky cookie bars over content.

**Backgrounds.** No photography is available in the source repo, so the system is illustration-free by default: flat sand, white cards, and two low-contrast warm washes (`--wash-hero`, `--wash-sand`) for hero and section grounds. No repeating patterns, no textures, no noise, no flag motifs (explicitly rejected in the source: the product must read as professional infrastructure, not a regional or travel brand). **Blue-purple gradients are banned.** When photography is eventually commissioned, the brief is: warm daylight, real German workplaces (logistics halls, workshops, care settings, classrooms), real people mid-task, no stock handshakes, no cool blue grading, mild grain acceptable.

**Cards.** White surface, `--radius-lg` 20px, 1px `--sand-200` hairline border, `--shadow-card` (a warm ink-tinted double shadow). Interactive cards add `--shadow-lift` and a −2px translate on hover, and scale to 0.985 on press. No coloured left borders. No card-inside-card — nest with `tone="sunken"` instead.

**Elevation.** Four steps only: `hairline` (dividers), `card` (resting), `lift` (hover/dragged), `overlay` (dialogs, menus, popovers). All shadows are tinted `rgba(30,24,21,…)` so they warm rather than grey the sand.

**Radii.** 6 / 10 / 14 / 20 / 28 / pill. Controls and inputs 14px, cards 20px, panels and hero media 28px, badges and avatars pill. Nothing is square.

**Borders.** 1px hairlines in sand tones do the structural work; `--border-width-strong` 1.5px only on stepper dots and selected states. Dividers use `--border-subtle`, interactive edges `--border-default`, hover `--border-strong`.

**Animation.** Short and eased: 90ms press, 140ms colour/hover, 200ms lift and reveal, 320ms progress and drawers. `--ease-standard` for state changes, `--ease-out` for entrances. Fades and ≤4px translates only — **no bounce, no spring, no looping attention-seekers, no parallax**. Progress bars animate their width; that is the most expressive motion in the system. `prefers-reduced-motion` reduces every duration to 0.01ms (enforced in `tokens/base.css`).

**Hover / press / focus / disabled.**
- Hover: one step darker (`--primary-hover`), plus shadow lift on cards; ghost/outline fill with a sand tint. Never opacity-only hover.
- Press: `--primary-active` plus `scale(0.985)`.
- Focus: a 2px rose ring at 2px offset (`--focus-ring`) — always visible on keyboard focus, never removed.
- Disabled: opacity 0.45 and pointer-events off; never a grey-on-grey redraw.

**Transparency & blur.** Used in exactly two places: the sticky marketing header after scroll (`--glass-surface` + `--glass-blur`), and modal scrims. Tints (`--*-tint`) are solid concrete colours, never alpha over an unknown ground — the source repo has a regression test for this, because `color-mix()` on a `light-dark()` value silently computes to transparent.

**Protection gradients vs capsules.** When text must sit on an image, use `--protection-gradient` (a bottom-up ink fade) — not a translucent capsule. Capsules (pill badges) are reserved for status, so using one for legibility would confuse the vocabulary.

**Data display.** Tabular numbers in mono, right-aligned in tables. A progress bar always prints its number as text beside it. Match scores appear with their reasons, never as a bare percentage.

---

## ICONOGRAPHY

**The source repo contains no icon set.** `apps/web/public/` holds only `robots.txt`; the live homepage renders its journey flow with a bare `→` character. There is no icon font, no SVG sprite, no PNG icon set to copy.

**Substitution (flagged):** this system uses **Lucide** (`lucide-static` via jsDelivr CDN) — 24px grid, 2px stroke, rounded caps and joins, which matches the warm geometric type better than a sharper set like Heroicons. Icons render through the `Icon` component as a **CSS mask**, so a glyph always inherits `currentColor` and can never drift off-palette.

Rules:
- Icons are decorative by default (`aria-hidden`); meaning lives in adjacent text. Never an icon-only button without an `aria-label`.
- Stroke icons only. Never mix filled and stroke sets. Never recolour a glyph outside the token palette.
- Sizes: 16px inline with 15px text, 18px default, 20–22px in nav and cards, 24px maximum in-product.
- No emoji, ever. Unicode arrows (`→`, `↓`) are permitted as flow connectors in diagrams only.
- House glyph set: `compass` (Karriere-Kompass), `search` (Chancen), `wallet` (Karriere-Mappe), `shield-check` (verified), `landmark` (official source), `graduation-cap` (Weiterbildung), `briefcase` (Jobs), `file-text` (Beratungsvorbereitung), `external-link`, `flag` (Angebot melden), `bell`, `settings`.

**Logo:** the source repo contains **no logo or brand mark**. None has been drawn or approximated here. Everywhere a mark would go, the wordmark is set in type — Mona Sans 800, −3.5% tracking, with the final "o" in `--primary` (see the *Wordmark* card under Brand). `assets/` therefore contains no logo file; if an official mark exists, drop it in as `assets/logo.svg` and it will be picked up by the project thumbnail automatically.

---

## Index

**Root**
- `styles.css` — the single entry point consumers link. `@import` lines only.
- `readme.md` — this file.
- `SKILL.md` — Agent-Skills-compatible entry point.
- `github.md` — source-repo association and sync record.
- `thumbnail.html` — homepage tile for this design system.

**Tokens** (`tokens/`) — `fonts.css`, `colors.css`, `typography.css`, `spacing.css`, `elevation.css`, `motion.css`, `base.css`

**Components** (`components/`) — `components.css` holds every `.bd-*` class; each component reads tokens only.

| Directory | Components |
| --- | --- |
| `components/core/` | **Button**, **Input**, **Label**, **Card** (+ `CardHeader`, `CardTitle`, `CardDescription`, `CardContent`), **Badge**, **Alert**, **Spinner** |
| `components/patterns/` | **Icon**, **Stepper**, **Progress**, **SourceTag** |

`core/` is exactly the inventory `packages/ui/src/index.ts` exports — nothing added, nothing dropped.

**Intentional additions** (`components/patterns/`, all four absent from `packages/ui` but required by the specification):
- **Icon** — wrapper for the substituted Lucide set, so glyph size and colour stay consistent.
- **Stepper** — README §5 mandates stepper UI for the 10-step candidate onboarding.
- **Progress** — the spec surfaces `Profil 70 % vollständig` and match scores; no bar existed.
- **SourceTag** — README §11 makes source metadata mandatory on every opportunity.

**Guidelines** (`guidelines/`) — 18 foundation specimen cards: colour ramps (rose, ink, sand, semantic, surfaces, provenance), type (display, headings, body, mono), spacing (scale, radii, density in use), brand (elevation, washes, motion, interaction states, wordmark).

**UI kits** (`ui_kits/`)
- `ui_kits/website/` — public marketing site: homepage, Chancen (opportunity search), Trust Center.
- `ui_kits/candidate-app/` — signed-in product: dashboard, Karriere-Kompass, Chancen-Hub, Förder-Navigator, Karriere-Mappe.

**Assets** (`assets/`) — see `assets/README.md`. No logo and no imagery exist in the source; nothing has been fabricated.
