@conciso/design-system 0.0.0-bootstrap.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +1786 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +15 -0
  4. package/README.md +134 -0
  5. package/assets/brand/LICENSE +11 -0
  6. package/assets/brand/README.md +45 -0
  7. package/assets/brand/logo-conciso-dark.svg +4 -0
  8. package/assets/brand/logo-conciso-light.svg +4 -0
  9. package/assets/brand/logo-conciso.svg +4 -0
  10. package/css/base.css +303 -0
  11. package/css/components.css +1633 -0
  12. package/css/dark-mode.css +716 -0
  13. package/css/fonts.css +20 -0
  14. package/css/tokens.css +209 -0
  15. package/dist/conciso-ds.css +2891 -0
  16. package/fonts/LibreBaskerville-OFL.txt +93 -0
  17. package/fonts/Montserrat-OFL.txt +93 -0
  18. package/fonts/libre-baskerville-400-latin-ext.woff2 +0 -0
  19. package/fonts/libre-baskerville-400-latin.woff2 +0 -0
  20. package/fonts/libre-baskerville-400i-latin-ext.woff2 +0 -0
  21. package/fonts/libre-baskerville-400i-latin.woff2 +0 -0
  22. package/fonts/libre-baskerville-700-latin-ext.woff2 +0 -0
  23. package/fonts/libre-baskerville-700-latin.woff2 +0 -0
  24. package/fonts/montserrat-300-latin-ext.woff2 +0 -0
  25. package/fonts/montserrat-300-latin.woff2 +0 -0
  26. package/fonts/montserrat-400-latin-ext.woff2 +0 -0
  27. package/fonts/montserrat-400-latin.woff2 +0 -0
  28. package/fonts/montserrat-400i-latin-ext.woff2 +0 -0
  29. package/fonts/montserrat-400i-latin.woff2 +0 -0
  30. package/fonts/montserrat-500-latin-ext.woff2 +0 -0
  31. package/fonts/montserrat-500-latin.woff2 +0 -0
  32. package/fonts/montserrat-700-latin-ext.woff2 +0 -0
  33. package/fonts/montserrat-700-latin.woff2 +0 -0
  34. package/icons/LICENSE-heroicons +21 -0
  35. package/icons/README.md +186 -0
  36. package/icons/icons.js +1156 -0
  37. package/icons/icons.json +1152 -0
  38. package/icons/manifest.json +595 -0
  39. package/icons/source/co-building.svg +1 -0
  40. package/icons/source/co-mark.svg +1 -0
  41. package/icons/source/es-window-check.svg +1 -0
  42. package/icons/source/ki-bot.svg +1 -0
  43. package/icons/source/ui-academic-cap.svg +1 -0
  44. package/icons/source/ui-adjustments-horizontal.svg +1 -0
  45. package/icons/source/ui-arrow-down-tray-2.svg +1 -0
  46. package/icons/source/ui-arrow-down-tray.svg +1 -0
  47. package/icons/source/ui-arrow-path.svg +1 -0
  48. package/icons/source/ui-arrow-trending-up.svg +1 -0
  49. package/icons/source/ui-banknotes.svg +1 -0
  50. package/icons/source/ui-bars-3-center-left.svg +1 -0
  51. package/icons/source/ui-bars-3.svg +1 -0
  52. package/icons/source/ui-bolt-2.svg +1 -0
  53. package/icons/source/ui-bolt.svg +1 -0
  54. package/icons/source/ui-book-open.svg +1 -0
  55. package/icons/source/ui-briefcase-2.svg +1 -0
  56. package/icons/source/ui-briefcase.svg +1 -0
  57. package/icons/source/ui-building-office.svg +1 -0
  58. package/icons/source/ui-calendar-days.svg +1 -0
  59. package/icons/source/ui-calendar.svg +1 -0
  60. package/icons/source/ui-caret-down.svg +1 -0
  61. package/icons/source/ui-chart-bar.svg +1 -0
  62. package/icons/source/ui-chat-bubble-left-right.svg +1 -0
  63. package/icons/source/ui-chat-bubble-oval-left-ellipsis.svg +1 -0
  64. package/icons/source/ui-chat-bubble-oval.svg +1 -0
  65. package/icons/source/ui-check-badge.svg +1 -0
  66. package/icons/source/ui-check-circle-2.svg +1 -0
  67. package/icons/source/ui-check-circle.svg +1 -0
  68. package/icons/source/ui-check.svg +1 -0
  69. package/icons/source/ui-chevron-down.svg +1 -0
  70. package/icons/source/ui-chevron-up-down.svg +1 -0
  71. package/icons/source/ui-circle-stack.svg +1 -0
  72. package/icons/source/ui-clock.svg +1 -0
  73. package/icons/source/ui-code-bracket-2.svg +1 -0
  74. package/icons/source/ui-code-bracket-square.svg +1 -0
  75. package/icons/source/ui-code-bracket.svg +1 -0
  76. package/icons/source/ui-cog-6tooth.svg +1 -0
  77. package/icons/source/ui-cog.svg +1 -0
  78. package/icons/source/ui-computer-desktop.svg +1 -0
  79. package/icons/source/ui-cpu-chip-2.svg +1 -0
  80. package/icons/source/ui-cpu-chip.svg +1 -0
  81. package/icons/source/ui-cube-2.svg +1 -0
  82. package/icons/source/ui-cube-transparent.svg +1 -0
  83. package/icons/source/ui-cube.svg +1 -0
  84. package/icons/source/ui-currency-euro.svg +1 -0
  85. package/icons/source/ui-cursor-arrow-rays.svg +1 -0
  86. package/icons/source/ui-device-phone-mobile.svg +1 -0
  87. package/icons/source/ui-document-text.svg +1 -0
  88. package/icons/source/ui-face-smile.svg +1 -0
  89. package/icons/source/ui-flag.svg +1 -0
  90. package/icons/source/ui-folder.svg +1 -0
  91. package/icons/source/ui-hand-raised.svg +1 -0
  92. package/icons/source/ui-heart.svg +1 -0
  93. package/icons/source/ui-information-circle.svg +1 -0
  94. package/icons/source/ui-language.svg +1 -0
  95. package/icons/source/ui-link.svg +1 -0
  96. package/icons/source/ui-list-bullet.svg +1 -0
  97. package/icons/source/ui-lock-closed-2.svg +1 -0
  98. package/icons/source/ui-lock-closed.svg +1 -0
  99. package/icons/source/ui-magnifying-glass.svg +1 -0
  100. package/icons/source/ui-map-pin-2.svg +1 -0
  101. package/icons/source/ui-map-pin.svg +1 -0
  102. package/icons/source/ui-megaphone.svg +1 -0
  103. package/icons/source/ui-newspaper-2.svg +1 -0
  104. package/icons/source/ui-newspaper.svg +1 -0
  105. package/icons/source/ui-pause.svg +1 -0
  106. package/icons/source/ui-pencil-square.svg +1 -0
  107. package/icons/source/ui-photo.svg +1 -0
  108. package/icons/source/ui-play.svg +1 -0
  109. package/icons/source/ui-puzzle-piece.svg +1 -0
  110. package/icons/source/ui-quote.svg +1 -0
  111. package/icons/source/ui-rectangle-stack.svg +1 -0
  112. package/icons/source/ui-rocket-launch.svg +1 -0
  113. package/icons/source/ui-shield-check-2.svg +1 -0
  114. package/icons/source/ui-shield-check.svg +1 -0
  115. package/icons/source/ui-sparkles-2.svg +1 -0
  116. package/icons/source/ui-sparkles-3.svg +1 -0
  117. package/icons/source/ui-sparkles-4.svg +1 -0
  118. package/icons/source/ui-sparkles.svg +1 -0
  119. package/icons/source/ui-square-2-stack.svg +1 -0
  120. package/icons/source/ui-squares-2x2.svg +1 -0
  121. package/icons/source/ui-squares-plus.svg +1 -0
  122. package/icons/source/ui-star-2.svg +1 -0
  123. package/icons/source/ui-star.svg +1 -0
  124. package/icons/source/ui-sun.svg +1 -0
  125. package/icons/source/ui-swatch.svg +1 -0
  126. package/icons/source/ui-table-cells.svg +1 -0
  127. package/icons/source/ui-tag.svg +1 -0
  128. package/icons/source/ui-trophy-2.svg +1 -0
  129. package/icons/source/ui-trophy.svg +1 -0
  130. package/icons/source/ui-user-group-2.svg +1 -0
  131. package/icons/source/ui-user-group.svg +1 -0
  132. package/icons/source/ui-users-2.svg +1 -0
  133. package/icons/source/ui-users.svg +1 -0
  134. package/icons/source/ui-viewfinder-circle.svg +1 -0
  135. package/icons/source/ui-window.svg +1 -0
  136. package/icons/source/ui-wrench-screwdriver.svg +1 -0
  137. package/icons/source/wo-network.svg +1 -0
  138. package/package.json +87 -0
  139. package/tokens/tokens.js +229 -0
  140. package/tokens/tokens.json +227 -0
  141. package/tokens/tokens.scss +228 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Conciso GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,15 @@
1
+ NOTICE
2
+
3
+ Dieses Repository steht unter der MIT-Lizenz (siehe LICENSE), mit folgenden
4
+ Ausnahmen:
5
+
6
+ - Logos und Wortmarken unter assets/brand/: Eigentum der Conciso GmbH, nicht
7
+ unter der MIT-Lizenz dieses Repositories. Siehe assets/brand/LICENSE.
8
+ - Schriften (Montserrat, Libre Baskerville) unter fonts/: SIL Open Font
9
+ License 1.1. Siehe fonts/Montserrat-OFL.txt und
10
+ fonts/LibreBaskerville-OFL.txt.
11
+ - Icons unter icons/source/ui-*.svg (generische UI-Icons, nicht die
12
+ Bereichs-Glyphen co-*/ki-*/es-*/wo-*): überwiegend aus Heroicons
13
+ (https://heroicons.com) übernommen oder abgeleitet, teils angepasst.
14
+ Copyright (c) Tailwind Labs, Inc., MIT-Lizenz, siehe
15
+ icons/LICENSE-heroicons.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # Conciso Design System
2
+
3
+ Das Design System von Conciso: **Design Tokens + CSS-Komponenten + Light/Dark-Mode**, framework-agnostisch und auf **WCAG 2.1 Stufe AA** ausgelegt (also alle Kriterien der Stufen A und AA; AAA wo ohne Nachteil erreichbar, aber nicht als Bedingung). Keine Build-Pflicht für die Nutzung — die Komponenten sind CSS-Klassen, die auf semantisches HTML angewendet werden, plus optionales Vanilla-JS für interaktive Muster (Theme-Toggle, Topnav-Dropdowns).
4
+
5
+ > **Status:** Inhaltlich stabil. Distribution (npm-Paket), Token-Export und Repo-Hygiene werden gerade ergänzt — siehe die GitHub-Releases dieses Repos und den eingefrorenen Stand im [CHANGELOG](CHANGELOG.md).
6
+
7
+ ## Für wen?
8
+
9
+ - **Entwickler:innen**, die Conciso-Oberflächen bauen (Website, CMS-Templates, künftig Framework-Apps).
10
+ - **Designer:innen**, die Komponenten, Tokens und Konventionen nachschlagen.
11
+
12
+ ## Dokumentation ansehen
13
+
14
+ Die vollständige, navigierbare Doku-Site liegt im Repo:
15
+
16
+ ```bash
17
+ # Repo klonen, dann die Doku-Site im Browser öffnen
18
+ open docs/index.html # macOS
19
+ # oder einen kleinen Static-Server im Repo-Root starten und /docs/ öffnen:
20
+ npx serve .
21
+ ```
22
+
23
+ Sie enthält 35 Sektionen in sechs Gruppen: **Marke** (Markenrad, Brand Areas, Logo, Bildsprache), **Grundlagen** (Farben, Typografie, Spacing, Responsive, Elevation, Design Tokens, Icons, Barrierefreiheit), **Komponenten** mit Code-Snippets und Do/Don'ts, **Seitenmuster** (Wissensbeitrag, Veranstaltung, Seminar und die zugehörigen Übersichten), **Beispielseiten** als komplette Seiten und **Referenzen**.
24
+
25
+ ## Nutzung im eigenen Projekt
26
+
27
+ Ausführlich in [docs/GETTING-STARTED.md](docs/GETTING-STARTED.md). Kurzfassung:
28
+
29
+ **Variante A — CSS direkt einbinden** (funktioniert heute, kein Build):
30
+
31
+ ```html
32
+ <!-- Self-Host-Fonts (DSGVO: keine Google-CDN-Anfrage) -->
33
+ <link rel="stylesheet" href="css/fonts.css">
34
+
35
+ <!-- Design System: REIHENFOLGE EINHALTEN -->
36
+ <link rel="stylesheet" href="css/tokens.css">
37
+ <link rel="stylesheet" href="css/dark-mode.css">
38
+ <link rel="stylesheet" href="css/base.css">
39
+ <link rel="stylesheet" href="css/components.css">
40
+ ```
41
+
42
+ Die Schriften (Montserrat + Libre Baskerville) liegen self-hosted unter `fonts/` und werden über `css/fonts.css` eingebunden — keine externe CDN-Anfrage. Das gebündelte `dist/conciso-ds.css` enthält die `@font-face`-Regeln bereits.
43
+
44
+ **Variante B — als npm-Paket von npmjs.org** (der empfohlene Weg):
45
+
46
+ ```bash
47
+ npm install @conciso/design-system
48
+ ```
49
+ ```js
50
+ import '@conciso/design-system/dist/conciso-ds.css';
51
+ // Tokens (optional, für JS/Framework):
52
+ import { tokens } from '@conciso/design-system/tokens';
53
+ // Icons (optional, maschinenlesbar — komplette <svg>-Bodies, currentColor):
54
+ import { icons } from '@conciso/design-system/icons';
55
+ // Brand-Logo (Wortmarke, drei Varianten):
56
+ import logo from '@conciso/design-system/assets/brand/logo-conciso.svg';
57
+ ```
58
+
59
+ Keine `.npmrc` nötig — das Paket liegt auf der öffentlichen npm-Registry, `npm install`
60
+ funktioniert ohne weitere Einrichtung. Siehe [ADR-0011](docs/adr/0011-veroeffentlichung-auf-npmjs.md).
61
+ Gilt ab dem ersten echten Release nach dem Merge dieser Änderung; bis dahin liegt auf
62
+ npmjs nur eine Bootstrap-Platzhalterversion (siehe ADR-0011).
63
+
64
+ Die Wortmarke liegt als SVG unter [`assets/brand/`](assets/brand/README.md) (Default, Light, Dark). Größen, Schutzraum und Verwendung stehen in der Doku unter **Marke → Logo**.
65
+
66
+ > Das Paket steht unter der [MIT-Lizenz](LICENSE) (Ausnahmen — Brand-Assets, Schriften,
67
+ > Icons — siehe [NOTICE](NOTICE)).
68
+ >
69
+ > **Alternative — GitHub Packages** (weiterhin verfügbar, unverändert, z. B. für
70
+ > Consumer innerhalb der GitHub-Organisation `conciso`): eine `.npmrc`, die den
71
+ > `@conciso`-Scope umleitet, plus ein Token mit Scope `read:packages` auch fürs Lesen
72
+ > (in GitHub Actions genügt `secrets.GITHUB_TOKEN`):
73
+ > ```ini
74
+ > @conciso:registry=https://npm.pkg.github.com
75
+ > //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
76
+ > ```
77
+ > GitHub Packages verlangt diese Auth wegen der **Registry**, nicht wegen der Lizenz.
78
+ > Details in [Getting Started](docs/GETTING-STARTED.md#1-einbinden), Begründung in
79
+ > [ADR-0004](docs/adr/0004-verteilung-und-versionierung.md). Ohne npm bleibt Variante A
80
+ > (Vendoren von `dist/conciso-ds.css` + `fonts/`) der schlankeste Weg.
81
+ >
82
+ > Die **Doku** (Storybook, die Komponenten-Referenz der Angular-Lib) ist öffentlich
83
+ > einsehbar unter <https://conciso.github.io/conciso-design-system/> — ohne Auth, aber
84
+ > `noindex` (nicht für Suchmaschinen bestimmt). Details und Abwägung in
85
+ > [ADR-0009](docs/adr/0009-storybook-oeffentlich-auf-github-pages.md).
86
+
87
+ **Angular:** Für Angular gibt es Komponenten statt nur CSS-Klassen —
88
+ `@conciso/design-system-angular` aus denselben beiden Registries, im Lockstep auf
89
+ derselben Version. Siehe [README der Lib](angular-lib/projects/design-system-angular/README.md).
90
+
91
+ **Dark Mode:** `data-theme="dark"` am `<html>` setzen. Siehe [Getting Started](docs/GETTING-STARTED.md#3-dark-mode) für das Anti-Flash-Snippet.
92
+
93
+ **Erstes Element:**
94
+
95
+ ```html
96
+ <button class="btn btn-filled btn-co">Kontakt</button>
97
+ <p style="font:var(--ty-body-md);color:var(--tx-primary)">Fließtext.</p>
98
+ ```
99
+
100
+ ## Verzeichnisse
101
+
102
+ | Pfad | Inhalt |
103
+ |---|---|
104
+ | `css/` | `tokens.css` · `dark-mode.css` · `base.css` · `components.css` (Ladereihenfolge!) — der konsumierbare Kern |
105
+ | `dist/` | `conciso-ds.css` (gebündelt, generiert) |
106
+ | `tokens/` | `tokens.json` · `tokens.scss` · `tokens.js` (Token-Export, generiert) |
107
+ | `icons/` | `icons.json` · `icons.js` · `README.md` (Icon-Export, generiert) + `source/*.svg` (Quelle) |
108
+ | `fonts/` | Self-Host-Fonts (woff2) + OFL-Lizenztexte; eingebunden über `css/fonts.css` |
109
+ | `scripts/` | `build-tokens.mjs` · `build-icons.mjs` · `bundle-css.mjs` (`npm run build`) · `check-dark-states.mjs` · `check-contrast.mjs` |
110
+ | `docs/` | Doku-/Showcase-Site: `index.html` · `main.js` · `assets/images/` · `GETTING-STARTED.md` |
111
+
112
+ > Der konsumierbare Teil (`css/`, `dist/`, `tokens/`, `icons/`) liegt im Root, die Doku-Site in `docs/`. Das npm-Paket enthält nur den Kern (kein `docs/`, keine Bilder). Icon-Details und Mapping: [`icons/README.md`](icons/README.md).
113
+
114
+ ## Mitwirken / Erweitern
115
+
116
+ Konventionen und der Workflow zum Hinzufügen von Tokens/Komponenten stehen in **[CONTRIBUTING.md](CONTRIBUTING.md)** — bitte vor Änderungen lesen. Das ist der Kern für eine konsistente, nachhaltige Pflege.
117
+
118
+ ### Prüfungen
119
+
120
+ ```bash
121
+ npm run build # Tokens, Icons, gebündeltes CSS (dist/ ist eingecheckt)
122
+ npm run check:dark-states # Zustands-Regeln, die im Dark dunkel-auf-dunkel laufen
123
+ npm run check:contrast # Kontrast der gerenderten Doku in Light UND Dark
124
+ ```
125
+
126
+ `check:contrast` rendert `docs/index.html` in beiden Modi in Chromium und prüft Text (4,5:1 bzw. 3:1 bei Großtext), getönte Bauteil-Füllungen und Bedienelement-Grenzen (3:1). Es misst die **fertige Kette** und findet damit auch inline gesetzte Farben, die kein Token-Check sieht. Der Stand ist **0 Verstöße**; jede Abweichung meldet das Skript mit Pfad, Farbe und Sollwert (`--list` zeigt jeden Fund einzeln). Es braucht einen Browser; die Playwright-Abhängigkeit dafür hängt am `storybook-angular`-Workspace und kommt mit dem `npm install` **im Repo-Wurzelverzeichnis** mit (npm-Workspaces, das Skript findet sie auch hoisted); lokal genügt ein installiertes Chrome. In der Pipeline läuft es in `storybook-angular.yml`.
127
+
128
+ ## Versionierung
129
+
130
+ [SemVer](https://semver.org/lang/de/). Die Version steht **nicht** im Repo, sondern im jeweiligen Git-Tag `vX.Y.Z`; Änderungen dazu stehen im zugehörigen GitHub-Release. Releases entstehen automatisch aus Conventional Commits auf `main` ([ADR-0010](docs/adr/0010-release-ausloesung-und-versionsquelle.md)) und werden nach npmjs.org **und** GitHub Packages veröffentlicht ([ADR-0011](docs/adr/0011-veroeffentlichung-auf-npmjs.md)). Der handgeschriebene [CHANGELOG](CHANGELOG.md) ist mit Version 2.0.0 eingefroren. `@conciso/design-system` und `@conciso/design-system-angular` tragen dabei im **Lockstep** immer dieselbe Version, damit die peerDependency der Angular-Lib auf die CSS-Schicht eng gepinnt auflöst ([ADR-0004](docs/adr/0004-verteilung-und-versionierung.md)).
131
+
132
+ ## Lizenz & Kontakt
133
+
134
+ MIT, siehe [LICENSE](LICENSE). Ausnahmen (Brand-Assets unter `assets/brand/`, Schriften, Icons) siehe [NOTICE](NOTICE). Fragen und Beiträge über GitHub Issues im Repo. Maintainer: _Design-System-Team (bitte eintragen)_.
@@ -0,0 +1,11 @@
1
+ Conciso-Logos und -Wortmarken
2
+
3
+ Copyright (c) 2026 Conciso GmbH. Alle Rechte vorbehalten.
4
+
5
+ Die Logos und Wortmarken der Marke Conciso in diesem Verzeichnis sind keine
6
+ Software im Sinne der MIT-Lizenz dieses Repositories (siehe LICENSE im
7
+ Repository-Root). Sie bleiben Eigentum der Conciso GmbH und dürfen
8
+ ausschließlich zur Darstellung der Marke Conciso verwendet werden, etwa in
9
+ Anwendungen, die mit diesem Design System gebaut werden. Jede andere Nutzung,
10
+ Veränderung oder Weitergabe bedarf der ausdrücklichen Genehmigung der
11
+ Conciso GmbH.
@@ -0,0 +1,45 @@
1
+ # Brand-Assets
2
+
3
+ Die Conciso-Wortmarke in drei Varianten. Verbindlich für Größen, Schutzraum und
4
+ Verwendung ist die Doku-Sektion **Marke → Logo** (`docs/index.html`, `#sec-logo`);
5
+ dieses Dokument beschreibt nur die Dateien und den Einbau.
6
+
7
+ **Lizenz:** Anders als der Rest des Repositories (MIT, siehe [`LICENSE`](../../LICENSE))
8
+ stehen diese Dateien nicht unter MIT. Sie bleiben Eigentum der Conciso GmbH,
9
+ siehe [`LICENSE`](LICENSE) in diesem Verzeichnis.
10
+
11
+ | Datei | Einsatz |
12
+ |---|---|
13
+ | `logo-conciso.svg` | Default. Wortmarke in `--tx-brand`, Punkt in `--co-500`. Helle Hintergründe |
14
+ | `logo-conciso-light.svg` | Vollständig weiß. Dunkle Hintergründe, Footer, Dark Mode |
15
+ | `logo-conciso-dark.svg` | Monochrom in `--tx-brand`, ohne Punkt. Druck, Stempel, einfarbig |
16
+
17
+ ## Einbau
18
+
19
+ Immer als SVG per `<img>`, nie als PNG oder JPG. Der Wechsel zwischen Light und
20
+ Dark läuft über die portablen Klassen `.logo-themed-default` und
21
+ `.logo-themed-light` aus `css/components.css`, rein per CSS und ohne JavaScript:
22
+
23
+ ```html
24
+ <span class="ep-logo">
25
+ <img class="logo-themed-default" src="assets/brand/logo-conciso.svg" alt="Conciso">
26
+ <img class="logo-themed-light" src="assets/brand/logo-conciso-light.svg" alt="" aria-hidden="true">
27
+ </span>
28
+ ```
29
+
30
+ Die Höhe ist das Leitmaß, die Breite ergibt sich proportional. `.ep-logo img`
31
+ setzt bereits `height:24px;width:auto`.
32
+
33
+ Als Paket-Abhängigkeit liegen die Dateien unter
34
+ `@conciso/design-system/assets/brand/logo-conciso.svg`.
35
+
36
+ ## Warum hier `width` und `height` am SVG stehen bleiben
37
+
38
+ `CONTRIBUTING.md` § 10 schreibt für `icons/source/` vor, `width` und `height`
39
+ weglassen. Das gilt dort, weil Icons inline eingebettet werden und die Attribute
40
+ die Größensteuerung per CSS behindern.
41
+
42
+ Logos werden per `<img>` eingebunden. Dort liefern genau diese Attribute dem
43
+ Browser das intrinsische Seitenverhältnis (2400 zu 314, also etwa 7,6 zu 1) und
44
+ verhindern Layout-Shift beim Laden. Die Attribute sind hier also Absicht und
45
+ keine Nachlässigkeit, bitte nicht gegen die Icon-Regel „aufräumen“.
@@ -0,0 +1,4 @@
1
+ <svg width="2400" height="314" viewBox="0 0 2400 314" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M2345.69 200.172C2330.17 200.172 2317.23 205.408 2306.89 215.857C2296.55 226.315 2291.38 239.86 2291.38 256.491C2291.38 272.654 2296.55 286.199 2306.89 297.124C2317.23 308.051 2330.17 313.522 2345.69 313.522C2361.67 313.522 2374.72 308.177 2384.83 297.479C2394.94 286.786 2400 273.133 2400 256.491C2400 239.86 2394.94 226.315 2384.83 215.857C2374.72 205.408 2361.67 200.172 2345.69 200.172Z" fill="#333E48"/>
3
+ <path d="M153.206 312.283C210.82 312.283 244.96 291.58 275.687 258.367L233.863 215.666C210.392 237.232 189.481 251.035 155.341 251.035C104.129 251.035 68.7082 207.9 68.7082 156.141V155.28C68.7082 103.519 104.983 61.2493 155.341 61.2493C185.214 61.2493 208.685 74.1894 231.729 95.3244L273.553 46.5843C245.812 18.9793 212.098 0 155.767 0C64.0148 0 0 70.3073 0 156.141V157.004C0 243.702 65.2951 312.283 153.206 312.283ZM497.183 312.283C589.363 312.283 656.363 241.975 656.363 156.141V155.28C656.363 69.4442 590.215 0 498.035 0C405.857 0 338.855 70.3073 338.855 156.141V157.004C338.855 242.84 405.003 312.283 497.183 312.283ZM498.035 251.035C445.118 251.035 407.564 207.9 407.564 156.141V155.28C407.564 103.519 444.264 61.2493 497.183 61.2493C550.101 61.2493 587.655 104.382 587.655 156.141V157.004C587.655 208.765 550.954 251.035 498.035 251.035ZM740.435 307.107H805.302V115.165L949.972 307.107H1005.88V5.17756H941.01V191.08L801.035 5.17756H740.435V307.107ZM1243.88 312.283C1301.49 312.283 1335.63 291.58 1366.36 258.367L1324.54 215.666C1301.06 237.232 1280.15 251.035 1246.01 251.035C1194.8 251.035 1159.38 207.9 1159.38 156.141V155.28C1159.38 103.519 1195.66 61.2493 1246.01 61.2493C1275.89 61.2493 1299.36 74.1894 1322.4 95.3244L1364.22 46.5843C1336.49 18.9793 1302.77 0 1246.44 0C1154.69 0 1090.67 70.3073 1090.67 156.141V157.004C1090.67 243.702 1155.97 312.283 1243.88 312.283ZM1455.75 307.107H1521.47V5.17756H1455.75V307.107ZM1737.17 311.421C1801.61 311.421 1846.85 277.777 1846.85 217.821V216.96C1846.85 164.338 1812.7 142.34 1752.09 126.381C1700.46 113.01 1687.66 106.538 1687.66 86.6971V85.8355C1687.66 71.1705 1700.88 59.5244 1726.06 59.5244C1751.25 59.5244 1777.28 70.7382 1803.74 89.2852L1837.87 39.2526C1807.58 14.6649 1770.45 0.863179 1726.92 0.863179C1665.89 0.863179 1622.37 37.0954 1622.37 91.8732V92.7363C1622.37 152.692 1661.21 169.514 1721.38 185.04C1771.3 197.98 1781.55 206.608 1781.55 223.43V224.291C1781.55 241.975 1765.33 252.76 1738.45 252.76C1704.3 252.76 1676.14 238.526 1649.25 216.097L1610.42 263.112C1646.27 295.46 1691.93 311.421 1737.17 311.421ZM2073.01 312.283C2165.19 312.283 2232.19 241.975 2232.19 156.141V155.28C2232.19 69.4442 2166.05 0 2073.86 0C1981.69 0 1914.69 70.3073 1914.69 156.141V157.004C1914.69 242.84 1980.83 312.283 2073.01 312.283ZM2073.86 251.035C2020.95 251.035 1983.4 207.9 1983.4 156.141V155.28C1983.4 103.519 2020.1 61.2493 2073.01 61.2493C2125.93 61.2493 2163.48 104.382 2163.48 156.141V157.004C2163.48 208.765 2126.78 251.035 2073.86 251.035Z" fill="#333E48"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="2400" height="314" viewBox="0 0 2400 314" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M2345.69 200.172C2330.17 200.172 2317.23 205.408 2306.89 215.857C2296.55 226.315 2291.38 239.86 2291.38 256.491C2291.38 272.654 2296.55 286.199 2306.89 297.124C2317.23 308.051 2330.17 313.522 2345.69 313.522C2361.67 313.522 2374.72 308.177 2384.83 297.479C2394.94 286.786 2400 273.133 2400 256.491C2400 239.86 2394.94 226.315 2384.83 215.857C2374.72 205.408 2361.67 200.172 2345.69 200.172Z" fill="white"/>
3
+ <path d="M153.206 312.283C210.82 312.283 244.96 291.58 275.687 258.367L233.863 215.666C210.392 237.232 189.481 251.035 155.341 251.035C104.129 251.035 68.7082 207.9 68.7082 156.141V155.28C68.7082 103.519 104.983 61.2493 155.341 61.2493C185.214 61.2493 208.685 74.1894 231.729 95.3244L273.553 46.5844C245.812 18.9793 212.098 0 155.767 0C64.0148 0 0 70.3073 0 156.141V157.004C0 243.702 65.2951 312.283 153.206 312.283ZM497.183 312.283C589.363 312.283 656.363 241.975 656.363 156.141V155.28C656.363 69.4442 590.215 0 498.035 0C405.857 0 338.855 70.3073 338.855 156.141V157.004C338.855 242.84 405.003 312.283 497.183 312.283ZM498.035 251.035C445.118 251.035 407.564 207.9 407.564 156.141V155.28C407.564 103.519 444.264 61.2493 497.183 61.2493C550.101 61.2493 587.655 104.382 587.655 156.141V157.004C587.655 208.765 550.954 251.035 498.035 251.035ZM740.435 307.107H805.302V115.165L949.972 307.107H1005.88V5.17756H941.01V191.08L801.035 5.17756H740.435V307.107ZM1243.88 312.283C1301.49 312.283 1335.63 291.58 1366.36 258.367L1324.54 215.666C1301.06 237.232 1280.15 251.035 1246.01 251.035C1194.8 251.035 1159.38 207.9 1159.38 156.141V155.28C1159.38 103.519 1195.66 61.2493 1246.01 61.2493C1275.89 61.2493 1299.36 74.1894 1322.4 95.3244L1364.22 46.5844C1336.49 18.9793 1302.77 0 1246.44 0C1154.69 0 1090.67 70.3073 1090.67 156.141V157.004C1090.67 243.702 1155.97 312.283 1243.88 312.283ZM1455.75 307.107H1521.47V5.17756H1455.75V307.107ZM1737.17 311.421C1801.61 311.421 1846.85 277.777 1846.85 217.821V216.96C1846.85 164.338 1812.7 142.34 1752.09 126.381C1700.46 113.01 1687.66 106.538 1687.66 86.6971V85.8355C1687.66 71.1705 1700.88 59.5244 1726.06 59.5244C1751.25 59.5244 1777.28 70.7382 1803.74 89.2851L1837.87 39.2526C1807.58 14.6649 1770.45 0.863179 1726.92 0.863179C1665.89 0.863179 1622.37 37.0955 1622.37 91.8732V92.7363C1622.37 152.692 1661.21 169.514 1721.38 185.04C1771.3 197.98 1781.55 206.608 1781.55 223.43V224.291C1781.55 241.975 1765.33 252.76 1738.45 252.76C1704.3 252.76 1676.14 238.526 1649.25 216.097L1610.42 263.112C1646.27 295.46 1691.93 311.421 1737.17 311.421ZM2073.01 312.283C2165.19 312.283 2232.19 241.975 2232.19 156.141V155.28C2232.19 69.4442 2166.05 0 2073.86 0C1981.69 0 1914.69 70.3073 1914.69 156.141V157.004C1914.69 242.84 1980.83 312.283 2073.01 312.283ZM2073.86 251.035C2020.95 251.035 1983.4 207.9 1983.4 156.141V155.28C1983.4 103.519 2020.1 61.2493 2073.01 61.2493C2125.93 61.2493 2163.48 104.382 2163.48 156.141V157.004C2163.48 208.765 2126.78 251.035 2073.86 251.035Z" fill="white"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="2400" height="314" viewBox="0 0 2400 314" version="1.1" xmlns="http://www.w3.org/2000/svg" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
2
+ <path d="M2345.69,200.173C2330.17,200.173 2317.23,205.408 2306.89,215.857C2296.55,226.315 2291.38,239.861 2291.38,256.492C2291.38,272.654 2296.55,286.199 2306.89,297.125C2317.23,308.052 2330.17,313.522 2345.69,313.522C2361.67,313.522 2374.72,308.178 2384.83,297.48C2394.94,286.787 2400,273.133 2400,256.492C2400,239.861 2394.94,226.315 2384.83,215.857C2374.72,205.408 2361.67,200.173 2345.69,200.173Z" style="fill:rgb(0,190,190);fill-rule:nonzero;"/>
3
+ <path d="M153.206,312.283C210.82,312.283 244.96,291.58 275.687,258.367L233.863,215.666C210.392,237.232 189.481,251.035 155.341,251.035C104.129,251.035 68.708,207.9 68.708,156.141L68.708,155.28C68.708,103.519 104.983,61.249 155.341,61.249C185.214,61.249 208.685,74.189 231.729,95.324L273.553,46.584C245.812,18.979 212.098,0 155.767,0C64.015,0 0,70.307 0,156.141L0,157.004C0,243.702 65.295,312.283 153.206,312.283ZM497.183,312.283C589.363,312.283 656.363,241.975 656.363,156.141L656.363,155.28C656.363,69.444 590.215,0 498.035,0C405.857,0 338.855,70.307 338.855,156.141L338.855,157.004C338.855,242.84 405.003,312.283 497.183,312.283ZM498.035,251.035C445.118,251.035 407.564,207.9 407.564,156.141L407.564,155.28C407.564,103.519 444.264,61.249 497.183,61.249C550.101,61.249 587.655,104.382 587.655,156.141L587.655,157.004C587.655,208.765 550.954,251.035 498.035,251.035ZM740.435,307.107L805.302,307.107L805.302,115.165L949.972,307.107L1005.88,307.107L1005.88,5.178L941.01,5.178L941.01,191.08L801.035,5.178L740.435,5.178L740.435,307.107ZM1243.88,312.283C1301.49,312.283 1335.63,291.58 1366.36,258.367L1324.54,215.666C1301.06,237.232 1280.15,251.035 1246.01,251.035C1194.8,251.035 1159.38,207.9 1159.38,156.141L1159.38,155.28C1159.38,103.519 1195.66,61.249 1246.01,61.249C1275.89,61.249 1299.36,74.189 1322.4,95.324L1364.22,46.584C1336.49,18.979 1302.77,0 1246.44,0C1154.69,0 1090.67,70.307 1090.67,156.141L1090.67,157.004C1090.67,243.702 1155.97,312.283 1243.88,312.283ZM1455.75,307.107L1521.47,307.107L1521.47,5.178L1455.75,5.178L1455.75,307.107ZM1737.17,311.421C1801.61,311.421 1846.85,277.777 1846.85,217.821L1846.85,216.96C1846.85,164.338 1812.7,142.34 1752.09,126.381C1700.46,113.01 1687.66,106.538 1687.66,86.697L1687.66,85.836C1687.66,71.171 1700.88,59.524 1726.06,59.524C1751.25,59.524 1777.28,70.738 1803.74,89.285L1837.87,39.253C1807.58,14.665 1770.45,0.863 1726.92,0.863C1665.89,0.863 1622.37,37.095 1622.37,91.873L1622.37,92.736C1622.37,152.692 1661.21,169.514 1721.38,185.04C1771.3,197.98 1781.55,206.608 1781.55,223.43L1781.55,224.291C1781.55,241.975 1765.33,252.76 1738.45,252.76C1704.3,252.76 1676.14,238.526 1649.25,216.097L1610.42,263.112C1646.27,295.46 1691.93,311.421 1737.17,311.421ZM2073.01,312.283C2165.19,312.283 2232.19,241.975 2232.19,156.141L2232.19,155.28C2232.19,69.444 2166.05,0 2073.86,0C1981.69,0 1914.69,70.307 1914.69,156.141L1914.69,157.004C1914.69,242.84 1980.83,312.283 2073.01,312.283ZM2073.86,251.035C2020.95,251.035 1983.4,207.9 1983.4,156.141L1983.4,155.28C1983.4,103.519 2020.1,61.249 2073.01,61.249C2125.93,61.249 2163.48,104.382 2163.48,156.141L2163.48,157.004C2163.48,208.765 2126.78,251.035 2073.86,251.035Z" style="fill:rgb(51,62,72);fill-rule:nonzero;"/>
4
+ </svg>
package/css/base.css ADDED
@@ -0,0 +1,303 @@
1
+ /* ── Base: Reset · Layout · Global ── */
2
+
3
+ /* ════════════════════════════════════════════
4
+ SYSTEM HIGH CONTRAST (Windows / OS level)
5
+ @media (forced-colors: active)
6
+ ════════════════════════════════════════════ */
7
+ @media (forced-colors: active) {
8
+ /* box-shadow is suppressed by OS – replace focus rings with outline */
9
+ :focus-visible {
10
+ outline: 3px solid Highlight !important;
11
+ outline-offset: 2px !important;
12
+ box-shadow: none !important;
13
+ }
14
+ /* Custom button backgrounds need explicit forced-color mapping */
15
+ .btn-filled {
16
+ forced-color-adjust: none;
17
+ background: ButtonText;
18
+ color: ButtonFace;
19
+ border: 2px solid ButtonText;
20
+ }
21
+ .btn-tonal,
22
+ .btn-elevated,
23
+ .btn-text,
24
+ .btn-outlined {
25
+ color: ButtonText;
26
+ border-color: ButtonText;
27
+ background: ButtonFace;
28
+ box-shadow: none;
29
+ }
30
+ /* Restore borders that forced-colors removes */
31
+ .chip { border: 2px solid ButtonText }
32
+ .card,
33
+ .card-elevated,
34
+ /* .stoerer liegt über einem Foto und verlässt sich im Light auf --bd-strong plus --e1.
35
+ Im Kontrastmodus fällt der Schatten weg, der 1px-Rand allein trägt die Kachel dann nicht
36
+ mehr gegen das Bild ab — gleiche 2px wie bei den übrigen Kartenflächen. */
37
+ .stoerer { border: 2px solid CanvasText }
38
+ .badge { border: 1px solid ButtonText; background: ButtonFace; color: ButtonText }
39
+ /* Active states */
40
+ .nav-item.active { border-left-color: Highlight; color: Highlight }
41
+ .atab.active { border-bottom-color: Highlight; color: Highlight }
42
+ .tbtn.active { forced-color-adjust: none; background: Highlight; color: HighlightText }
43
+ /* Links in footer */
44
+ .footer-link,
45
+ .footer-btm-link { color: LinkText }
46
+ /* Skip link */
47
+ .skip-link { background: Highlight; color: HighlightText; border: 2px solid ButtonText }
48
+ /* Sidebar toggle */
49
+ .sidebar-toggle { border: 1px solid ButtonText; color: ButtonText }
50
+ /* Form inputs */
51
+ .field input,
52
+ .field select,
53
+ .field textarea { border: 2px solid ButtonText; color: CanvasText; background: Canvas }
54
+ /* Code blocks */
55
+ .code-block { border: 1px solid CanvasText }
56
+ }
57
+
58
+ /* ── Reset ── */
59
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
60
+ body{font-family:var(--font);font-size:1rem;line-height:1.7;color:var(--tx-primary);background:var(--bg-page);transition:background var(--m-std),color var(--m-std)}
61
+
62
+ /* ── Skip link ── */
63
+ /* Fläche co-700, nicht co-500: weiß auf #00BEBE trägt nur 2,31:1 und verfehlt AA für Normaltext.
64
+ In Ruhe ist der Link geclippt, beim Fokus springt er sichtbar herein, also genau dann, wenn
65
+ Tastaturnutzende ihn brauchen. co-700 (#007575) trägt weiß mit 5,52:1 und ist zugleich die
66
+ Füllfarbe, die .btn-filled.btn-co verwendet. Gilt in beiden Modi, co-* flippt nicht. */
67
+ .skip-link{position:absolute;top:-100px;left:var(--s4);background:var(--co-700);color:#fff;padding:var(--s2) var(--s4);border-radius:var(--r-md);font-weight:600;font-size:0.875rem;z-index:9999;transition:top var(--m-fast);border:none;cursor:pointer;font-family:var(--font)}
68
+ .skip-link:focus{top:var(--s4)}
69
+
70
+ /* ── Layout ── */
71
+ .ds-page{display:flex;min-height:100vh}
72
+ .ds-sidebar{width:252px;flex-shrink:0;background:var(--bg-surface);border-right:var(--bd);padding:var(--s8) 0;position:sticky;top:0;height:100vh;overflow-y:auto;overflow-x:hidden;transition:width var(--m-std)}
73
+ .ds-content{flex:1;padding:var(--s10) var(--s6);max-width:1280px;transition:margin-left var(--m-std)}
74
+ /* Vorschau-Modus (≤ 1024px): Doku-Sidebar ausblenden und horizontalen Content-Abstand
75
+ auf 0, damit die Beispielseiten exakt die Fensterbreite einnehmen. Sonst quetscht die
76
+ feste 252px-Sidebar die .ep-page in eine Restspalte, während ihre @media-Queries die
77
+ volle Fensterbreite lesen — Container-Breite und Breakpoint passen dann nicht zusammen
78
+ und die Mobile/Tablet-Vorschau wird unbrauchbar. So stimmen .ep-page-Breite und Breakpoint
79
+ überein → DevTools-Geräte-Modus und Fenster-Verkleinern zeigen die Seite faithful.
80
+ Die Beispielseiten-Tabs liegen im Content (nicht in der Sidebar), bleiben also erreichbar. */
81
+ @media (max-width: 1024px) {
82
+ .ds-sidebar{display:none}
83
+ .ds-content{padding-inline:0}
84
+ }
85
+
86
+ /* ── Sidebar ── */
87
+ .nav-logo{padding:0 var(--s6) var(--s6);border-bottom:var(--bd);margin-bottom:var(--s5);display:flex;align-items:center;justify-content:space-between;gap:var(--s2)}
88
+ /* --co-ink, nicht co-500: die Signalfarbe trägt auf Weiß nur 2,31:1. Das Ink-Token flippt mit dem
89
+ Theme (Light co-700, Dark co-200), ein festes co-700 wäre im Dark 2,36:1 auf der Sidebar. */
90
+ .nav-logo-text{font:500 0.75rem/1rem var(--font);letter-spacing:.02em;text-transform:uppercase;color:var(--co-ink);white-space:nowrap;overflow:hidden;transition:opacity var(--m-std),width var(--m-std)}
91
+
92
+ /* ── Sidebar toggle button ── */
93
+ .sidebar-toggle{background:none;border:none;cursor:pointer;padding:4px;border-radius:var(--r-xs);color:var(--tx-secondary);display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:background var(--m-fast),color var(--m-fast)}
94
+ .sidebar-toggle:hover{background:var(--bg-overlay);color:var(--tx-primary)}
95
+ .sidebar-toggle:focus-visible{outline:none;box-shadow:var(--focus-aa)}
96
+ .sidebar-toggle svg{transition:transform var(--m-std)}
97
+
98
+ /* ── Sidebar collapsed state ── */
99
+ .ds-sidebar.collapsed{width:56px}
100
+ .ds-sidebar.collapsed .nav-logo{padding:0 0 var(--s6);justify-content:center}
101
+ .ds-sidebar.collapsed .nav-logo-text{opacity:0;width:0;overflow:hidden}
102
+ .ds-sidebar.collapsed .sidebar-toggle svg{transform:rotate(180deg)}
103
+ .ds-sidebar.collapsed .nav-section,.ds-sidebar.collapsed .nav-subnav{display:none}
104
+ .ds-sidebar.collapsed .nav-item{justify-content:center;padding:var(--s2) 0;font-size:0;gap:0}
105
+ .ds-sidebar.collapsed .nav-icon{width:20px;height:20px;opacity:.6}
106
+ .ds-sidebar.collapsed .nav-item:hover .nav-icon{opacity:1}
107
+ .ds-sidebar.collapsed .nav-item.active .nav-icon{opacity:1}
108
+ /* .nav-section ist ein <h2> (Screenreader-Outline der Nav-Gruppen) — UA-Heading-Margins zurücksetzen */
109
+ .nav-section{margin:0;padding:var(--s3) var(--s6) var(--s1);font:500 0.75rem/1rem var(--font);letter-spacing:.08em;text-transform:uppercase;color:var(--tx-muted)}
110
+ /* Nav-Gruppen als Liste (Screenreader: „Liste, N Einträge“); Default-Einrückung/Bullets entfernen */
111
+ .nav-list{list-style:none;margin:0;padding:0}
112
+ /* Größerer Abstand vor jeder folgenden Gruppen-Überschrift (visuelle Trennung der Bereiche);
113
+ die erste Gruppe braucht ihn nicht, sie ist bereits durch das Logo/den Rahmen getrennt. */
114
+ .nav-list + .nav-section{margin-top:var(--s4)}
115
+ .nav-item{display:flex;align-items:center;gap:var(--s2);padding:7px var(--s6);font:500 0.875rem/1.25rem var(--font);color:var(--tx-secondary);cursor:pointer;border-left:3px solid transparent;transition:background var(--m-fast),color var(--m-fast),border-color var(--m-fast);background:none;border-top:none;border-right:none;border-bottom:none;width:100%;text-align:left}
116
+ .nav-item:hover{background:var(--bg-overlay);color:var(--tx-primary)}
117
+ .nav-item:focus-visible{outline:none;box-shadow:var(--focus-aa)}
118
+ /* Aktiver Eintrag: Text co-700 (co-500 #00BEBE auf co-50 war nur 2,07:1 → co-700 = 4,95:1, WCAG 1.4.3).
119
+ Akzentbalken co-600 (3,28:1 auf Weiß, WCAG 1.4.11). Zustand zusätzlich über font-weight (nicht nur Farbe → 1.4.1). */
120
+ .nav-item.active{color:var(--co-700);background:var(--co-50);border-left-color:var(--co-600);font-weight:600}
121
+ .nav-icon{width:18px;height:18px;flex-shrink:0;opacity:.7;fill:none;stroke:currentColor;stroke-width:1.5}
122
+ .nav-item.active .nav-icon{opacity:1}
123
+ .area-dot{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0}
124
+
125
+ /* ── Sections ── */
126
+ .ds-section{display:none}
127
+ .ds-section.visible{display:block}
128
+ .sec-title{font:400 2rem/2.5rem var(--font-display);color:var(--tx-primary);margin-bottom:var(--s2)}
129
+ .sec-sub{font:400 1rem/1.5rem var(--font);color:var(--tx-secondary);margin-bottom:var(--s8)}
130
+ .group-title{font:400 1.5rem/2rem var(--font-display);color:var(--tx-primary);margin:var(--s10) 0 var(--s4);padding-top:var(--s6);border-top:var(--bd)}
131
+ .lbl{font:500 0.75rem/1rem var(--font);letter-spacing:.07em;text-transform:uppercase;color:var(--tx-muted);display:block;margin-bottom:var(--s2)}
132
+ .row{display:flex;flex-wrap:wrap;gap:var(--s4);align-items:flex-start}
133
+ .token{font-family:var(--font-mono);font-size:0.75rem;color:var(--co-700);background:var(--co-50);padding:2px 7px;border-radius:var(--r-xs)}
134
+
135
+ /* ── Theme switcher ── */
136
+ .theme-bar{position:fixed;top:var(--s3);right:var(--s4);display:flex;gap:var(--s2);z-index:200;background:var(--bg-surface);border:var(--bd-strong);border-radius:var(--r-full);padding:4px;box-shadow:var(--e2)}
137
+ .tbtn{display:inline-flex;align-items:center;gap:6px;padding:5px var(--s3);border-radius:var(--r-full);border:none;cursor:pointer;font:500 0.75rem/1rem var(--font);background:transparent;color:var(--tx-secondary);transition:background var(--m-fast),color var(--m-fast)}
138
+ .tbtn svg{width:14px;height:14px;flex:none}
139
+ .tbtn:focus-visible{outline:none;box-shadow:var(--focus-aa)}
140
+ /* Aktiv-Fläche co-700 statt co-500: weiß auf #007575 = 5,5:1 (AA) — co-500 #00BEBE war nur 2,3:1 (Fail bei 12px/500) */
141
+ .tbtn.active{background:var(--co-700);color:#fff}
142
+
143
+ /* ── Color palettes ── */
144
+ .pal-group{margin-bottom:var(--s8)}
145
+ .pal-label{font:500 0.875rem/1.25rem var(--font);color:var(--tx-secondary);margin-bottom:var(--s3);display:flex;align-items:center;gap:var(--s2)}
146
+ /* Die Reihe ist eine Karte: Haarlinie plus Rundung, Inhalt geklippt. Ohne den Rahmen verliert sie
147
+ im Light ihre Kante, weil die hellen Stufen (50, 100) und der weiße Beschriftungs-Streifen beide
148
+ fast die Farbe der Seite haben (#E0F7F7 gegen Weiß sind 1,12:1). Im Dark trennt sich der Streifen
149
+ von der Seite ohnehin, dort ist der Rahmen nur konsequent. Die Rundung liegt an der Karte, damit
150
+ sie oben UND unten greift; das Klippen betrifft nur die Ecken, nicht den Streifen. */
151
+ .pal-row{display:flex;gap:2px;border:1px solid var(--bd-c);border-radius:var(--r-md);overflow:hidden}
152
+ /* Farbfeld oben, Beschriftung auf einem neutralen Streifen darunter. Vorher saß die Beschriftung
153
+ AUF der Farbe, und dort lässt sich der Kontrast nicht garantieren: bei sieben von hundert Stufen
154
+ liegt die Leuchtdichte so in der Mitte, dass weder weiße noch dunkle Schrift 4,5:1 erreicht
155
+ (auf ki-700 schafft selbst reines Schwarz nur 4,82:1). Auf dem neutralen Streifen sind es überall
156
+ 6,28:1, in beiden Modi, und das Farbfeld bleibt unverdeckt. Der abzulesende Hexwert ist
157
+ Information, keine Dekoration, deshalb hat er einen Grund, auf dem er trägt. */
158
+ .swatch{position:relative;flex:1;min-height:104px;display:flex;flex-direction:column;justify-content:flex-end;padding:0;overflow:hidden}
159
+ /* Keine Deckkraft-Absenkung auf der Beschriftung: opacity .75 kostete jedes Label rund ein
160
+ Viertel Kontrast, und auf dem Swatch steht der Hexwert, den man ablesen soll. Die Farbe wird
161
+ je Swatch gesetzt (helle Fläche → dunkler Text und umgekehrt), das reicht als Abstufung. */
162
+ /* Der Streifen braucht Luft nach oben, sonst klebt die Beschriftung am Farbfeld. nowrap, weil ein
163
+ Umbruch ("800 T") das Farbfeld dieser einen Spalte nach oben schöbe und die Reihe eine Stufe
164
+ bekäme. */
165
+ /* Linie zwischen Farbfeld und Beschriftung: im Light grenzt der weiße Streifen sonst nicht gegen
166
+ die hellen Stufen ab. Sie sitzt auf der ersten Zeile des Streifens, also nur einmal je Spalte. */
167
+ .swatch span{font-size:0.75rem;font-family:var(--font-mono);font-weight:600;line-height:1.5;background:var(--bg-surface);color:var(--tx-secondary);padding:5px 6px 0;white-space:nowrap}
168
+ .swatch > span:first-of-type{border-top:1px solid var(--bd-c);padding-top:4px}
169
+ /* Eingeblendeter Hex-Code (nur Tonal-Paletten): kräftiger als das Stufen-Label, damit als Referenz ablesbar */
170
+ .swatch .swatch-hex{text-transform:uppercase;letter-spacing:.01em;padding:0 6px 5px}
171
+ /* Unter 1024 px wird eine Spalte zu schmal für den Hexwert. Er entfällt dann; der Wert steht
172
+ weiterhin im title-Attribut und wird per Klick kopiert (docs/main.js). Die Stufe bleibt. */
173
+ @media (max-width:1024px){ .swatch .swatch-hex{display:none} }
174
+ /* Klick-zum-Kopieren: Cursor + Fokus. Fokus-Ring als inset box-shadow (zwei Töne → auf hellen
175
+ UND dunklen Swatches sichtbar), da .pal-row overflow:hidden einen äußeren Ring abschneiden würde. */
176
+ .swatch.is-copyable,.clip-card.is-copyable{cursor:pointer}
177
+ .swatch.is-copyable:focus-visible,.swatch.is-copyable.is-copied{outline:none;box-shadow:inset 0 0 0 2px rgba(255,255,255,.95),inset 0 0 0 4px rgba(17,17,17,.9);z-index:1}
178
+ .clip-card.is-copyable:focus-visible{outline:none;box-shadow:var(--focus-ring)}
179
+ /* Bestätigung: Häkchen-Overlay (fit auch auf schmalen Swatches; SR-Ansage übernimmt der aria-live-Bereich) */
180
+ .swatch.is-copied::after{content:"✓";position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(17,17,17,.82);color:#fff;font:700 1rem/1 var(--font);border-radius:inherit}
181
+ .clip-card.is-copied{position:relative}
182
+ .clip-card.is-copied::after{content:"✓ Kopiert";position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(17,17,17,.82);color:#fff;font:600 0.875rem/1 var(--font)}
183
+ .ai-warning{margin-top:var(--s3);padding:var(--s3) var(--s4);background:var(--ki-50);border-radius:var(--r-md);font-size:0.75rem;color:var(--ki-800);border:1px solid var(--ki-200)}
184
+ .pal-note{margin-top:var(--s3);padding:var(--s3) var(--s4);background:var(--c-warning-bg);border-radius:var(--r-md);font-size:0.75rem;color:#5a3e00;border:1px solid #e8d080}
185
+ .pal-thresholds{margin-top:var(--s2);padding:var(--s2) var(--s4);background:#EDF4FF;border-radius:var(--r-md);font-size:0.75rem;color:#1a3a6b;border:1px solid #b8d0f0;font-family:var(--font-mono)}
186
+ .pal-thresholds .thr-badge{display:inline-block;padding:1px 6px;border-radius:3px;font-weight:700;margin-right:2px;font-size:0.75rem}
187
+ .thr-aa-l{background:#dbeeff;color:#1a3a6b}
188
+ .thr-aa{background:#c3f0e8;color:#0a4a38}
189
+ .thr-aaa{background:#e8d0ff;color:#3a1070}
190
+
191
+ /* ── Area specimen text (default: dark brand shade for light bg) ── */
192
+ [data-area="co"] .area-specimen-text{color:var(--co-700)}
193
+ [data-area="ki"] .area-specimen-text{color:var(--ki-800)}
194
+ [data-area="es"] .area-specimen-text{color:var(--es-700)}
195
+ [data-area="wo"] .area-specimen-text{color:var(--wo-700)}
196
+
197
+ /* ── Area cards ── */
198
+ .areas-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s6);margin-bottom:var(--s8)}
199
+ @media(max-width:768px){.areas-grid{grid-template-columns:1fr}}
200
+ .area-card{border-radius:var(--r-lg);border:var(--bd-strong);overflow:hidden;display:flex;flex-direction:column}
201
+ .area-header{padding:var(--s5) var(--s6);color:#fff}
202
+ .area-header h2{font:400 1rem/1.5rem var(--font-display);margin-bottom:4px}
203
+ .area-header p{font:400 0.75rem/1rem var(--font)}
204
+ .area-body{padding:var(--s4) var(--s6);background:var(--bg-surface);flex:1}
205
+ .area-swatch-row{display:flex;gap:3px;margin-bottom:var(--s3)}
206
+ .area-swatch{width:28px;height:28px;border-radius:var(--r-xs)}
207
+ .area-meta{font:400 0.75rem/1rem var(--font);color:var(--tx-secondary)}
208
+ .area-meta code{font-size:0.75rem;font-family:var(--font-mono)}
209
+
210
+ /* Utility: hartes Verstecken (überschreibt Inline-display) */
211
+ .is-hidden{display:none!important}
212
+
213
+ /* ── Layout Grid (12 Spalten · Gutter: var(--s6)=24px · Container: 1280px) ── */
214
+ .layout-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--s6)}
215
+ .col-1{grid-column:span 1}.col-2{grid-column:span 2}.col-3{grid-column:span 3}
216
+ .col-4{grid-column:span 4}.col-5{grid-column:span 5}.col-6{grid-column:span 6}
217
+ .col-7{grid-column:span 7}.col-8{grid-column:span 8}.col-9{grid-column:span 9}
218
+ .col-10{grid-column:span 10}.col-11{grid-column:span 11}.col-12{grid-column:span 12}
219
+ /* Kollabiert auf 1 Spalte. Wichtig: auch die col-*-Spannweiten zurücksetzen — sonst spannen
220
+ die Kinder weiter span 7/span 5/… und erzeugen bei nur einer 1fr-Spalte implizite Auto-Spalten,
221
+ wodurch unterschiedlich gespannte Geschwister (z. B. col-7 Text vs. col-5 Bild) verschieden
222
+ breit werden. Mit grid-column:auto ist jedes Kind exakt volle Breite. */
223
+ @media(max-width:768px){
224
+ .layout-grid{grid-template-columns:1fr}
225
+ .layout-grid>[class*="col-"]{grid-column:auto}
226
+ }
227
+ /* Team-Kacheln („Wer wir sind“): statt einspaltig untereinander als 2×2-Raster, damit die
228
+ vier Köpfe auf dem Phone kompakt bleiben. Override der col-3-Spannweite (3 → 1 Track). */
229
+ @media(max-width:768px){
230
+ .layout-grid[data-team-tiles]{grid-template-columns:1fr 1fr}
231
+ .layout-grid[data-team-tiles] > [data-team-tile]{grid-column:auto}
232
+ }
233
+ /* Team-Roster („Die Menschen“, Über uns): ~70 Personen sollen mobil nicht einspaltig als
234
+ endlose Liste laufen. Tablet (521–768px) → 3 Spalten (ab ~520px gibt das ≥ ~146px je Spalte,
235
+ genug Platz). Phone (≤ 520px) → 2 Spalten, sonst zu gedrängt. minmax(0,1fr) verhindert
236
+ Grid-Blowout durch lange Namen (Text wrappt). Engerer Gap (--s4). col-3-Spannweite → 1 Track.
237
+ 520px-Bruch konsistent mit dem Hero-CTA-Breakpoint. */
238
+ @media(max-width:768px){
239
+ .layout-grid[data-team-roster]{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4)}
240
+ .layout-grid[data-team-roster] > .col-3{grid-column:auto}
241
+ }
242
+ @media(max-width:520px){
243
+ .layout-grid[data-team-roster]{grid-template-columns:repeat(2,minmax(0,1fr))}
244
+ }
245
+ /* Benefits-Grid (4 Kategorien) und Event-Meta-Strip (4 Key-Facts: Datum/Ort/Format/Eintritt):
246
+ Tablet (521–768px) → 2×2 statt der einspaltigen layout-grid-Kollabierung; Smartphone (≤ 520px)
247
+ → 1×4 einspaltig. Desktop (> 768px) bleibt 4-spaltig. Die col-3-Spannweite setzt bereits die
248
+ globale Regel oben zurück. 520px-Bruch konsistent mit Roster/Hero-CTAs. */
249
+ @media(max-width:768px){
250
+ .layout-grid[data-benefits],.layout-grid[data-event-meta]{grid-template-columns:1fr 1fr}
251
+ }
252
+ @media(max-width:520px){
253
+ .layout-grid[data-benefits],.layout-grid[data-event-meta]{grid-template-columns:1fr}
254
+ }
255
+ /* Editorial-Split (Bild + Text nebeneinander): stapelt auf Mobile einspaltig, das Bild läuft
256
+ full-width. Der inline Text-Cap (max-width:520px, gedacht für die Zeilenlänge NEBEN dem Bild)
257
+ erzeugt dann eine Asymmetrie — Text schmaler als das Bild darüber. Unter dem Bild aufheben,
258
+ damit der Fließtext bündig zur Bildbreite läuft. !important, weil der Cap inline gesetzt ist;
259
+ greift nur auf .ep-section-sub INNERHALB eines layout-grid (Splits), nicht auf Sektions-Leads. */
260
+ @media(max-width:768px){
261
+ .layout-grid .ep-section-sub{max-width:none!important}
262
+ }
263
+
264
+ /* ── Utility: visuell versteckt, aber für Screenreader lesbar ── */
265
+ .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
266
+
267
+ /* ── Type Scale Utilities (15 Tokens) ── */
268
+ .type-display-lg{font:400 3.5625rem/4rem var(--font-display)}
269
+ .type-display-md{font:400 2.8125rem/3.25rem var(--font-display)}
270
+ .type-display-sm{font:400 2.25rem/2.75rem var(--font-display)}
271
+ .type-headline-lg{font:400 2rem/2.5rem var(--font-display)}
272
+ .type-headline-md{font:400 1.75rem/2.25rem var(--font-display)}
273
+ .type-headline-sm{font:400 1.5rem/2rem var(--font-display)}
274
+ .type-title-lg{font:500 1.375rem/1.75rem var(--font)}
275
+ .type-title-md{font:500 1rem/1.5rem var(--font)}
276
+ .type-title-sm{font:500 0.875rem/1.25rem var(--font)}
277
+ .type-body-lg{font:400 1rem/1.5rem var(--font)}
278
+ .type-body-md{font:400 0.875rem/1.25rem var(--font)}
279
+ .type-body-sm{font:400 0.75rem/1rem var(--font)}
280
+ .type-label-lg{font:500 0.875rem/1.25rem var(--font)}
281
+ .type-label-md{font:500 0.75rem/1rem var(--font)}
282
+ .type-label-sm{font:500 0.75rem/1rem var(--font);text-transform:uppercase;letter-spacing:.08em}
283
+
284
+ /* ── Sub-navigation ── */
285
+ .nav-subnav{display:none;padding-bottom:var(--s2)}
286
+ .nav-subnav.visible{display:block}
287
+ .nav-sub-item{display:block;padding:5px var(--s6) 5px 36px;font:var(--ty-body-xs);color:var(--tx-secondary);text-decoration:none;transition:background var(--m-fast),color var(--m-fast);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
288
+ .nav-sub-item::before{content:"–";opacity:.4;margin-right:6px;font-size:0.75rem}
289
+ .nav-sub-item:hover{color:var(--tx-primary);background:var(--bg-overlay)}
290
+ .nav-sub-item:focus-visible{outline:none;box-shadow:var(--focus-aa)}
291
+
292
+ /* ── Scroll margin for jump targets ── */
293
+ .group-title{scroll-margin-top:var(--s8)}
294
+
295
+ /* ── Back-to-top button ── */
296
+ /* co-600 statt co-500: weißes Caret braucht ≥3:1 (1.4.11) — co-600 = 3,29:1 (Icon), und der Button vs.
297
+ Seite ≥3:1 sowohl auf weiß (Light, 3,29) als auch auf bg-page (Dark, 3,32); co-500 verfehlt es im Light,
298
+ co-700 im Dark. visibility (mit-transitioniert) nimmt den versteckten Button aus der Tab-Reihenfolge —
299
+ sonst ist ein unsichtbares Fokusziel per Tab erreichbar. */
300
+ .back-to-top{position:fixed;bottom:var(--s8);right:var(--s6);width:44px;height:44px;border-radius:var(--r-full);background:var(--co-600);color:#fff;border:none;cursor:pointer;box-shadow:var(--e3);display:flex;align-items:center;justify-content:center;opacity:0;visibility:hidden;pointer-events:none;transition:opacity var(--m-std),visibility var(--m-std),box-shadow var(--m-fast);z-index:150}
301
+ .back-to-top.visible{opacity:1;visibility:visible;pointer-events:auto}
302
+ .back-to-top:hover{box-shadow:var(--e4)}
303
+ .back-to-top:focus-visible{outline:none;box-shadow:var(--focus-ring)}