@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
@@ -0,0 +1,716 @@
1
+ /* ── Dark Mode & Theme Overrides ── */
2
+
3
+ /* ════════════════════════════════════════════
4
+ DARK MODE
5
+ ════════════════════════════════════════════ */
6
+ /* @media screen umschließt die GANZE Datei, Token-Block und Komponenten-Regeln. Im Druck greifen
7
+ dadurch die Light-Werte aus tokens.css, ohne dass sie hier ein zweites Mal stehen (eine Kopie
8
+ wäre eine zweite Quelle der Wahrheit und würde auseinanderlaufen). Ohne das druckt eine Seite
9
+ mit data-theme="dark" die volle dunkle Fläche: sehr viel Farbauftrag, und auf vielen Druckern
10
+ heller Text auf grauem Grund.
11
+ Die Komponenten-Regeln müssen mit hinein: 183 von ihnen setzen eine helle Tint- oder Festfarbe
12
+ (co-200, ki-200, es-100, heller tx-primary). Auf dem hellen Druckgrund tragen die 1,2 bis 1,9:1,
13
+ die Zeile wäre also unlesbar. Nur den Token-Block zu schützen hätte den Text genau dort verloren,
14
+ wo eine eigene Dark-Regel greift. Neue Dark-Regeln deshalb immer INNERHALB dieses Blocks. */
15
+ @media screen {
16
+ [data-theme="dark"] {
17
+ /* Native Controls (Checkbox, Radio, Scrollbar, Select-Popup) im Dark-Theme rendern lassen,
18
+ statt hell-thematisiert auf dunklem Grund — sonst wirkt die Checkbox wie ein Fremdkörper. */
19
+ color-scheme: dark;
20
+ /* Surfaces: Flächen-Leiter nach der Material-Dark-Theme-Guidance.
21
+ Dark-only: bg-page #333E48 ❌ 10,92:1 gegen Weiß → #151A1F ✓ 17,51:1. (Light: #FFFFFF.)
22
+ Gefordert sind mindestens 15,8:1. Die Schwelle ist kein Stilmittel, sondern der Puffer, der
23
+ Fließtext auch auf der höchsten Elevationsstufe noch 4,5:1 sichert. Der Altwert war wörtlich
24
+ --tx-brand aus dem Light Mode, also eine gegen Weiß optimierte Textfarbe, keine Fläche.
25
+ Farbwinkel 209 (Slate) durchgehend, damit der Marken-Ton erhalten bleibt.
26
+ Dark-only: Stufe bg-page zu bg-surface ❌ 1,223:1 → ✓ 1,346:1. Trotz tieferer Basis wächst die
27
+ Tiefe, weil mehr Kopfraum nach unten mehr Spielraum nach oben schafft. */
28
+ --bg-page:#151A1F; --bg-surface:#28323D; --bg-overlay:rgba(0,190,190,.10);
29
+ /* Dark-only: bg-code #060D0D ❌ 1,12:1 gegen die neue Seite, der Well verschwand → #07090C ✓
30
+ 1,14:1, zusammen mit dem --bd-Rahmen ablesbar. (Light: n-800 als dunkler Well auf Weiß.) */
31
+ --bg-code:#07090C;
32
+ /* Dark-only: Hover interaktiver Flächen, 11,47:1. Die Schatten tragen auf 17,51:1 weniger als
33
+ auf dem alten #333E48, deshalb hebt der Zustand zusätzlich die Fläche. Entspricht etwa 14 dp
34
+ im Material-Overlay-Modell. Das ist ein Zustand, KEINE dritte statische Flächen-Stufe.
35
+ (Light: gleich bg-surface, dort trägt --e3 die Tiefe.) */
36
+ --bg-surface-hover:#2E3B46;
37
+ /* Dark-only: Logo-Platte #FFFFFF ❌ 17,51:1 gegen die Seite, blendet großflächig → #E8EDED ✓
38
+ 14,81:1. Dunkle Kundenlogos darauf weiterhin 14,73:1. (Light: #FFFFFF.) */
39
+ --bg-plate:#E8EDED;
40
+ /* Text */
41
+ --tx-brand:#C4D8D8; --tx-primary:#DDE9E9; --tx-secondary:#A6C6C6; --tx-muted:#93B6B6; /* tx-secondary #A6C6C6 → AA auf bg-surface-Cards (4.9:1); tx-muted von #7A9E9E auf #93B6B6 angehoben → AA auf bg-page (5.0:1), bg-surface 4.1:1, bleibt klar unter tx-secondary */
42
+ /* Neutrals (only lowest, used as bg/border), auf denselben Farbwinkel 209 gezogen.
43
+ Dark-only: n-100 #1C2E2E ❌ 1,09:1 gegen die neue bg-surface, Füllungen auf Cards
44
+ verschwanden → #1E262E ✓ 1,18:1 zur Card und 1,14:1 zur Seite, trägt also in beide
45
+ Richtungen. n-50 bleibt die tiefste Stufe, 19,25:1. (Light: #F5F7F7 / #E8EDED.) */
46
+ --n-50:#0B0F11; --n-100:#1E262E;
47
+ /* Borders. Dark-only: bd #818C99 ❌ auf der tieferen Seite 5,12:1, die Haarlinie wirkte drahtig
48
+ → #6F7A89 ✓ 4,02:1 auf der Seite, 2,99:1 auf der Card. bd ist dekorative Trennung, nicht das
49
+ alleinige Erkennungsmerkmal eines Bedienelements. (Light: n-100 / n-200.) */
50
+ --bd-c:#6F7A89; --bd-strong-c:#8694A5;
51
+ --bd:1px solid var(--bd-c); --bd-strong:1px solid var(--bd-strong-c);
52
+ /* Dark-only: field-border war n-200 #C9D3D3 ❌ 11,46:1 gegen die neue Seite, ein greller Rahmen
53
+ → #869C9C ✓ 6,04:1 auf der Seite und 4,49:1 auf der Card. Der Feldrahmen ist die einzige
54
+ Grenze, die WCAG 1.4.11 zwingend braucht, und liegt damit sicher über 3:1. (Light: n-400.) */
55
+ --field-border:#869C9C;
56
+ /* Focus: innerer Ring = bg-page für den Cutout-Effekt. Folgt jetzt dem Token statt einem
57
+ hartkodierten #333E48, dadurch laufen beide Ringe bei künftigen Flächen-Änderungen mit.
58
+ co-500 trägt 7,59:1 auf der Seite, 5,64:1 auf der Card, 4,98:1 auf der Hover-Card. */
59
+ --focus-ring:0 0 0 3px var(--bg-page),0 0 0 5px var(--co-500);
60
+ --focus-aa:0 0 0 2px var(--bg-page),0 0 0 4px var(--co-500);
61
+ /* Elevation – heavier shadows on dark */
62
+ --e1:0 1px 2px rgba(0,0,0,.60),0 1px 3px 1px rgba(0,0,0,.40);
63
+ --e2:0 1px 2px rgba(0,0,0,.60),0 2px 6px 2px rgba(0,0,0,.40);
64
+ --e3:0 1px 3px rgba(0,0,0,.60),0 4px 8px 3px rgba(0,0,0,.40);
65
+ --e4:0 2px 3px rgba(0,0,0,.70),0 6px 10px 4px rgba(0,0,0,.40);
66
+ --e5:0 4px 4px rgba(0,0,0,.70),0 8px 12px 6px rgba(0,0,0,.40);
67
+ /* Semantic backgrounds: Callout- und Badge-Tints, auf derselben Stufe wie die kleinen
68
+ Bereichs-Füllungen (9,8:1).
69
+ Dark-only: c-warning-bg #231800 ❌ 1,00:1 gegen die neue Seite, die Fläche war dort schlicht
70
+ unsichtbar → #544115 ✓ 1,79:1 zur Seite, 1,33:1 zur Card. success und error mitgezogen, damit
71
+ die drei Status-Flächen auf einer Stufe liegen. Statustexte darauf 5,2 bis 6,3:1.
72
+ (Light: helle Tints auf Weiß.) */
73
+ --c-success-bg:#1F573B; --c-warning-bg:#5F4B1E; --c-error-bg:#882725;
74
+ /* Semantic text colors: hellere Pendants für Lesbarkeit auf bg-page (#151A1F).
75
+ Light-Pendants in tokens.css. Verwendung: ✓/✕-Marker, Required-Asterisk, Inline-Fehlertext. */
76
+ --c-success:#5CE8A0; /* auf bg-page: 11.26:1 ✓ AAA · auf bg-surface: 8.37:1 ✓ AAA */
77
+ --c-warning:#F0C060; /* auf bg-page: 10.35:1 ✓ AAA · auf bg-surface: 7.69:1 ✓ AAA */
78
+ --c-error:#FFA5A5; /* auf bg-page: 9.32:1 ✓ AAA · auf bg-surface: 6.93:1 ✓ AAA. Angehoben von
79
+ #FF8E8E, das nur gegen bg-page geprüft war und auf bg-surface 4.0:1
80
+ erreichte. Inline-Fehlertext sitzt aber fast immer auf bg-surface. */
81
+ /* Brand tints (Dark), getrennt nach den zwei Jobs, die --XX-50 im Light in einem Wert erledigt.
82
+ Der Grund: Ein Band muss DUNKLER bleiben als die Karten darauf, eine Badge- oder Kachel-Füllung
83
+ muss HELLER sein als ihr Grund, sonst liest sie nicht als Fläche. Bei einer Basis von 17,51:1
84
+ ist der Spielraum zu klein, damit ein Wert beides trägt.
85
+
86
+ --XX-50 = kleine Fuellung (Badges, Pills, Icon-Kacheln, getoente Select-Flaechen).
87
+ ZWEI Kriterien, nicht eins: Der Kontrastquotient allein greift bei satten Farben zu kurz. Die
88
+ Vorgaengerwerte trugen 1,33:1 gegen die Karte, erfuellten den 1,3:1-Faustwert also, hatten aber
89
+ nur 8,3 L*-Punkte Helligkeitsabstand. Der Unterschied lag damit fast vollstaendig in Farbton
90
+ und Saettigung, und eine satte Flaeche auf gleicher Helligkeit liest als dunkler Fleck statt
91
+ als hellere Stufe; am deutlichsten bei ES, weil Blau bei gleichem L* am dunkelsten wirkt.
92
+ Jetzt um gut 4 L*-Punkte gehoben, Farbton und Saettigung unveraendert (a und b in Lab gleich
93
+ gelassen, nur L angehoben): Flaeche 1,54 bis 1,55:1 gegen die Karte, 2,07 bis 2,09:1 gegen
94
+ die Seite, Helligkeitsabstand 12,5 bis 12,7 L*. Text darauf 4,97:1 (wo, der knappste) bis
95
+ 6,64:1, helle -100-Glyphen 5,86 bis 7,34:1. Nach oben bleibt wenig Luft: der wo-Text liegt
96
+ 0,47 ueber AA. --ro-50 wird nicht als Fuellung eingesetzt (Rose ist Akzent- und Statusfarbe)
97
+ und bleibt unveraendert.
98
+ (Light: zarter Bereichstint auf Weiss, Bauteil-Fuellungen dort ueber --XX-fill.) */
99
+ --co-50:#134C47; --ki-50:#384912; --wo-50:#144E1F; --es-50:#253C92; --ro-50:#7E1F37;
100
+ /* --XX-band = große getönte Sektionsfläche (Hero, CTA-Band), 16,5:1. Die Bänder lagen früher
101
+ UNTER bg-page (14,0:1 gegen 10,9:1). Nach unten bleibt jetzt nur Faktor 1,20 bis Schwarz, sie
102
+ liegen deshalb knapp ÜBER der Seite und trennen sich von ihr primär über den Farbton statt über
103
+ die Helligkeit (1,06:1). Karten darauf behalten 1,27:1 und bilden weiter die hellere Stufe.
104
+ Sättigung auf 0,60 begrenzt: großflächig gesättigte Farbe „vibriert“ auf dunklem Grund.
105
+ (Light: identisch mit --XX-50, dort gibt es den Konflikt nicht.) */
106
+ --co-band:#092321; --ki-band:#1A2208; --wo-band:#09240E; --es-band:#111C44;
107
+ /* --XX-fill = Füllung kleiner Bauteile (Pill, Bereichs-Badge). Im Dark identisch mit --XX-50, das
108
+ hier ja schon auf genau diese Aufgabe kalibriert ist (1,78:1 zur Seite, 1,32:1 zur Karte). Das
109
+ Token existiert für den Light Mode, wo --XX-50 als Füllung nur 1,06 bis 1,14:1 trägt und
110
+ zugleich Sektions-Tint ist. OHNE diese vier Zeilen liefen Pill und Badge im Dark auf --XX-200,
111
+ also helle Füllung mit hellem Text. Wer --XX-50 im Dark anfasst, zieht diese Werte mit. */
112
+ /* Pill- und Badge-Fuellung im Dark: gehoben gegenueber dem ruhigen -50-Tint. Im Light traegt die
113
+ dunkle Schrift auf zartem Grund die Praesenz; im Dark ist es umgekehrt, helle Schrift auf
114
+ dunklem Tint, und bei fast gleicher Helligkeit wie die Karte haelt nichts mehr die Flaeche.
115
+ Deshalb hier 1,54 bis 1,55:1 zur Karte und 12,5 bis 12,7 L* Helligkeitsabstand, in Lab
116
+ gerechnet mit unveraendertem Farbton. Text darauf 4,97 bis 6,64:1. */
117
+ --co-fill:#1F5651; --ki-fill:#43531C; --es-fill:#34469D; --wo-fill:#205828;
118
+ /* Bereichs-Akzenttext im Dark: die hellen Pendants, gemessen auf der Seite 10,31 bis 13,79:1,
119
+ auf einer Karte 7,66 bis 10,25:1. Die Light-Werte (-700/-800) wären hier dunkel-auf-dunkel. */
120
+ --co-ink:var(--co-200); --ki-ink:var(--ki-200); --es-ink:var(--es-100); --wo-ink:var(--wo-200);
121
+ /* Badge text – lighter for dark backgrounds */
122
+ /* Dark-only: badge-err-text #F08080 ❌ 3,78:1 auf der aufgehellten Fehler-Füllung #802020
123
+ → #FFA5A5 ✓ 5,21:1. Damit derselbe Ton wie --c-error, eine Fehlerfarbe weniger im System.
124
+ (Light: #9b2020 auf hellem Tint.) */
125
+ --badge-ok-text:#5CE8A0; --badge-warn-text:#F0C060; --badge-err-text:#FFA5A5;
126
+ /* Neutraler Badge, gleiche Stufe wie die Bereichs-Badges, damit das Bild konsistent bleibt und
127
+ kein Sonder-Rahmen nötig ist. Dark-only: lag als var(--n-50) bei 1,10:1 gegen die Seite ❌
128
+ (n-50 ist die tiefste Flächenstufe und damit dunkler als der Grund, der Badge verschwand)
129
+ → eigener Wert #364553 ✓ 1,78:1 zur Seite, 1,32:1 zur Card, Text darauf 6,64:1.
130
+ (Light: var(--n-100).) */
131
+ --badge-neu-bg:#404F5D; --badge-neu-text:#C4D8D8;
132
+ /* Contrast badge (dark): auf derselben Stufe wie die Bereichs- und Status-Füllungen (9,8:1),
133
+ sonst stünden die Badges in den Kontrast-Tabellen flächengleich auf ihrem Grund.
134
+ Je 1,78 bis 1,79:1 zur Seite, 1,32 bis 1,33:1 zur Card, Text darauf 5,2 bis 6,3:1. */
135
+ --cbadge-aa-bg:#134D31; --cbadge-aa-text:#5CE8A0;
136
+ --cbadge-aaa-bg:#194864; --cbadge-aaa-text:#70C8F0;
137
+ --cbadge-fail-bg:#802020; --cbadge-fail-text:#FFA5A5; /* Dark-only: #F08080 ❌ 3,78:1 → 5,21:1 ✓ */
138
+ }
139
+ /* Dark: Brand Wheel. Die Ringe lagen unter der alten Seite (1,69:1 und 1,46:1). Gegen die tiefere
140
+ Seite fielen sie auf 1,06:1 und 1,10:1 und wären als Ringe verschwunden, deshalb wie die
141
+ Bereichs-Tints über die Seite gehoben: 1,16:1 und 1,40:1 zur Seite, 1,21:1 zueinander (vorher
142
+ 1,16:1). Die Divider-Striche laufen über var(--bg-page) und trennen die Ringe weiterhin. */
143
+ [data-theme="dark"] .bw-outer { fill: #0B2B2B }
144
+ [data-theme="dark"] .bw-middle { fill: #0E3A3A }
145
+ [data-theme="dark"] .bw-divider { stroke: var(--bg-page) }
146
+ [data-theme="dark"] .bw-ring-outline { stroke: var(--bg-page) }
147
+ [data-theme="dark"] .bw-label-segment { fill: var(--co-200) }
148
+ [data-theme="dark"] .bw-label-attr { fill: var(--co-300) }
149
+ [data-theme="dark"] .bw-pillar-card { background: var(--bg-surface) }
150
+ /* co-700 (#007575) on bg-surface (#28323D) = 2.36:1 → co-300 (#4DD0D0) = 6.97:1 ✓ AAA */
151
+ [data-theme="dark"] .bw-pillar-title { color: var(--co-300) }
152
+ /* Dark-only: tx-secondary (#A6C6C6) on bg-surface (#28323D) = 7.13:1 → tx-primary = 10.48:1, hier
153
+ bewusst die kräftigere Stufe, weil die Attribute im Rad als Primärinformation gelesen werden.
154
+ (Light: #4A6565 auf #fff = 6.28:1 ✓, kein Fix nötig.) */
155
+ [data-theme="dark"] .bw-pillar-attrs { color: var(--tx-primary) }
156
+ /* co-700 (#007575) on bg-page (#151A1F) = 3.17:1 ❌ für Normaltext → co-200 (#80DEDE) = 11.19:1 ✓ AAA */
157
+ [data-theme="dark"] .doc-eyebrow { color: var(--co-200) }
158
+
159
+ /* Dark: targeted component fixes that can't be token-driven */
160
+ /* Select arrow: n-500 (#4A6565) auf bg-surface (#28323D) = 2.07:1 ❌ → n-200 (#C9D3D3) = 8.51:1 ✓ */
161
+ [data-theme="dark"] .field select { background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23C9D3D3' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19.5 8.25l-7.5 7.5-7.5-7.5'/%3E%3C/svg%3E") }
162
+ /* Textarea-Resizer: der native Eck-Griff (dunkle Diagonalen) ist im Dark auf dem Feld-bg unsichtbar.
163
+ Eigenen hellen Griff (#C9D3D3, 5,84:1) als background-image aufs Textarea legen — zuverlässiger
164
+ positioniert als im winzigen ::-webkit-resizer-Pseudoelement — und den nativen Resizer transparent
165
+ schalten (Drag-Funktion bleibt). Firefox zeigt für resize:vertical keinen Eck-Griff. */
166
+ [data-theme="dark"] .field textarea {
167
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath d='M11 4L4 11M11 8L8 11' stroke='%23C9D3D3' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
168
+ background-repeat:no-repeat;
169
+ background-position:right 6px bottom 6px;
170
+ }
171
+ [data-theme="dark"] .field textarea::-webkit-resizer { background:transparent }
172
+ /* Slider: --sl-color = Thumb, --sl-text = Wert-Anzeige. Die -500/-700/-800-Töne fallen im Dark auf dem
173
+ dunklen Grund durch (Wert-Text ki/es/wo < 4,5:1, Thumb < 3:1). Beide auf die hellen -200/-100-Töne
174
+ heben (5,3-7:1). Track (--n-200 #C9D3D3) bleibt hell/sichtbar; disabled (.38 opacity) ist 1.4.3-ausgenommen. */
175
+ /* Dark-only: Der Slider OHNE Bereichsklasse fiel durchs Raster. Er nimmt den Fallback der
176
+ Komponente (--sl-text: co-700) und stand damit ❌ 2,36:1 auf der Karte, dunkel auf dunkel.
177
+ Die vier Bereichsklassen darunter waren gesetzt, der Grundfall nicht. → co-200 ✓ 8,32:1.
178
+ (Light: co-700 auf Weiß, 5,52:1.) */
179
+ [data-theme="dark"] .field-slider-output { color: var(--sl-text, var(--co-200)) }
180
+ [data-theme="dark"] .slider-co { --sl-color: var(--co-200); --sl-text: var(--co-200) }
181
+ [data-theme="dark"] .slider-ki { --sl-color: var(--ki-200); --sl-text: var(--ki-200) }
182
+ [data-theme="dark"] .slider-es { --sl-color: var(--es-100); --sl-text: var(--es-100) }
183
+ [data-theme="dark"] .slider-wo { --sl-color: var(--wo-200); --sl-text: var(--wo-200) }
184
+ /* Tick-Labels (min/mid/max): tx-muted reißt im Dark AA (~3:1) → tx-secondary (4,9:1) */
185
+ [data-theme="dark"] .field-slider-ticks { color: var(--tx-secondary) }
186
+ /* Such-Feld-Magnifier: stroke=var(--n-400) #6E8585 flippt nicht und liegt im Dark bei nur 2,28:1.
187
+ Das Icon trägt den „Such“-Kontext (nicht rein dekorativ) → auf tx-secondary heben (4,9:1).
188
+ CSS-stroke schlägt das Präsentationsattribut am <svg>. */
189
+ [data-theme="dark"] [role="search"] svg { stroke: var(--tx-secondary) }
190
+ /* Dropdowns (.ep-select/.ep-combobox): Caret n-500 (#4A6565) auf Feld-bg ≈ 1,1:1 → n-200 (#C9D3D3),
191
+ analog zur nativen Select-Pfeil-Korrektur oben. */
192
+ [data-theme="dark"] .ep-select-caret { color: var(--n-200); stroke: var(--n-200) }
193
+ /* Akzent des gewählten Eintrags: --sel-500 nutzt die -700/-800-Bereichstöne → dunkel-auf-dunkel auf der
194
+ bg-surface-Popup-Fläche bzw. der dunklen -50-Tönung. Auf die hellen -200/-100-Töne heben (wie t-Utilities,
195
+ Badges, Pills); die --sel-50-Tönung bleibt theme-aware (dunkle -50-Kachel), heller Text trägt den Kontrast. */
196
+ [data-theme="dark"] .ep-select, [data-theme="dark"] .ep-combobox { --sel-500: var(--co-200) }
197
+ [data-theme="dark"] .ep-select[data-area="ki"], [data-theme="dark"] .ep-combobox[data-area="ki"] { --sel-500: var(--ki-200) }
198
+ [data-theme="dark"] .ep-select[data-area="es"], [data-theme="dark"] .ep-combobox[data-area="es"] { --sel-500: var(--es-100) }
199
+ [data-theme="dark"] .ep-select[data-area="wo"], [data-theme="dark"] .ep-combobox[data-area="wo"] { --sel-500: var(--wo-200) }
200
+ /* Dark-only: Ruhe-Rand des neutralen Chips. Stand als hartkodiertes #818C99 da, dem alten --bd-Wert,
201
+ den die Flächen-Umstellung auf #6F7A89 gedämpft hat. Jetzt --bd-strong-c aus der Rahmen-Familie:
202
+ 4,21:1 gegen die Chip-Fläche und 5,66:1 gegen die Seite. --bd-c wäre hier zu schwach (2,99:1 zur
203
+ Chip-Fläche), der Chip-Rand ist eine Bedienelement-Grenze und braucht 3:1 nach WCAG 1.4.11.
204
+ (Light: n-200, 1.5px, aus components.css.) */
205
+ [data-theme="dark"] .chip { border-color: var(--bd-strong-c) }
206
+ /* Dark-only: Hover-Rand des neutralen Chips. Light geht auf n-400 (#6E8585), im Dark liegt das mit
207
+ 3,32:1 unter dem Ruhe-Rand: der Rand würde beim Überfahren schwächer statt kräftiger.
208
+ → n-200 = #C9D3D3, 8,51:1. (Light: n-400 bleibt.) */
209
+ [data-theme="dark"] .chip:hover { border-color: var(--n-200) }
210
+ /* Dark-only: Ruhezustand der BEREICHS-Chips. Sie setzen Rahmen und Text in components.css auf die
211
+ dunklen Stufen (-500/-600/-700 Rahmen, -700/-800 Text), die im Dark nicht flippen: der Text stand
212
+ damit ❌ 1,35:1 (es-700) bis 2,36:1 (co-700) auf einer Karte, also dunkel-auf-dunkel, und der
213
+ es-Rahmen mit 2,30:1 unter der 3:1-Schwelle für die Bedienelement-Grenze. Jetzt wie überall im
214
+ Dark die hellen Pendants: Text -200 (es -100), 7,66 bis 10,25:1 ✓; Rahmen -300, 4,25 bis 9,48:1 ✓,
215
+ eine Stufe unter dem Text, damit die Schrift dominant bleibt wie im Light.
216
+ Der Hover geht auf -200/-100 (auf der getönten Füllung 5,78 bis 7,77:1), also kräftiger als die
217
+ Ruhe, gleiche Richtung wie beim neutralen Chip. Die Hover-Füllung --XX-50 flippt schon selbst.
218
+ (Light: -500/-600/-700-Rahmen mit -700/-800-Text, unverändert.) */
219
+ [data-theme="dark"] .chip[data-area="co"] { border-color: var(--co-300); color: var(--co-200) }
220
+ [data-theme="dark"] .chip[data-area="ki"] { border-color: var(--ki-300); color: var(--ki-200) }
221
+ [data-theme="dark"] .chip[data-area="es"] { border-color: var(--es-300); color: var(--es-100) }
222
+ [data-theme="dark"] .chip[data-area="wo"] { border-color: var(--wo-300); color: var(--wo-200) }
223
+ [data-theme="dark"] .chip[data-area="co"]:hover { border-color: var(--co-200) }
224
+ [data-theme="dark"] .chip[data-area="ki"]:hover { border-color: var(--ki-200) }
225
+ [data-theme="dark"] .chip[data-area="es"]:hover { border-color: var(--es-100) }
226
+ [data-theme="dark"] .chip[data-area="wo"]:hover { border-color: var(--wo-200) }
227
+ /* Dark-only: Gedrückter Chip invertiert, wie das Segmented Control (dort --seg-fill -300 mit
228
+ --seg-on -900). Light füllt mit n-700 und schreibt weiß; im Dark ergäbe das eine sehr dunkle
229
+ Fläche auf dunklem Grund — ❌ 1,60:1 zwischen Chip und Seite, der ausgewählte Zustand war nur
230
+ noch am Text erkennbar. Helle Füllung n-300 mit dunklem Text n-900 ✓. Der Hover geht eine Stufe
231
+ heller (n-200) statt dunkler, damit die Richtung stimmt. (Light: n-700/n-800 bleiben.) */
232
+ [data-theme="dark"] .chip[aria-pressed="true"] { background: var(--n-300); border-color: var(--n-300); color: var(--n-900) }
233
+ [data-theme="dark"] .chip[aria-pressed="true"]:hover { background: var(--n-200); border-color: var(--n-200) }
234
+ /* Die Bereichs-Chips setzen ihren gewählten Zustand mit eigener Regel (--XX-700/800 + weißer Text) und
235
+ brauchen deshalb eigene Dark-Regeln — sonst greift oben die neutrale Füllung, der weiße Text bleibt
236
+ stehen und ergibt ❌ 1,53:1. Gleiche Inversion wie beim Segmented Control, jeweils Bereichston -300
237
+ mit -900-Text; Hover eine Stufe heller. (Light: -700/-800 mit Weiß bleiben.) */
238
+ [data-theme="dark"] .chip[data-area="co"][aria-pressed="true"] { background: var(--co-300); border-color: var(--co-300); color: var(--co-900) }
239
+ [data-theme="dark"] .chip[data-area="ki"][aria-pressed="true"] { background: var(--ki-300); border-color: var(--ki-300); color: var(--ki-900) }
240
+ [data-theme="dark"] .chip[data-area="es"][aria-pressed="true"] { background: var(--es-300); border-color: var(--es-300); color: var(--es-900) }
241
+ [data-theme="dark"] .chip[data-area="wo"][aria-pressed="true"] { background: var(--wo-300); border-color: var(--wo-300); color: var(--wo-900) }
242
+ [data-theme="dark"] .chip[data-area="co"][aria-pressed="true"]:hover { background: var(--co-200); border-color: var(--co-200) }
243
+ [data-theme="dark"] .chip[data-area="ki"][aria-pressed="true"]:hover { background: var(--ki-200); border-color: var(--ki-200) }
244
+ [data-theme="dark"] .chip[data-area="es"][aria-pressed="true"]:hover { background: var(--es-200); border-color: var(--es-200) }
245
+ [data-theme="dark"] .chip[data-area="wo"][aria-pressed="true"]:hover { background: var(--wo-200); border-color: var(--wo-200) }
246
+ /* Dark-only: Pause-Knopf im Logo-Karussell. Light dunkelt das Icon beim Hover auf n-700 (#1A2E2E),
247
+ im Dark sind das 1,60:1 auf der Karten-Fläche. → n-100 hebt es auf das hellste Neutral.
248
+ (Light: n-700 bleibt.) */
249
+ [data-theme="dark"] .logo-carousel-pause:hover { color: var(--n-200) }
250
+ [data-theme="dark"] .ai-warning { color:var(--ki-300) }
251
+ [data-theme="dark"] .pal-note { background:var(--c-warning-bg);color:#f0d080;border-color:#806000 }
252
+ /* Dark-only: Die Flächen standen hier als hartkodierte Kopien von --c-success-bg und --c-error-bg
253
+ (#052415 / #220808). Als die Status-Tints angehoben wurden, blieben die Kopien zurück und trugen
254
+ nur noch ❌ 1,06:1 bzw. 1,08:1 gegen die Seite, die Snackbar war als Fläche praktisch weg.
255
+ Jetzt über die Token ✓ 1,78:1 und 1,79:1; Text darauf 7,60:1 und 8,34:1. */
256
+ [data-theme="dark"] .snack-ok { background:var(--c-success-bg); color:#b0f0d0 }
257
+ [data-theme="dark"] .snack-err { background:var(--c-error-bg); color:#fde8e8 }
258
+ /* Dieselbe Familie wie die Snackbar darüber: die Kreisflächen standen als hartkodierte Kopien von
259
+ --c-success-bg und --c-error-bg (#052415 / #220808) und blieben beim Anheben der Status-Tints
260
+ zurück. Gegen die neue Seite trugen sie nur ❌ 1,06:1 bzw. 1,08:1, der Kreis war keine Fläche
261
+ mehr, nur noch ein farbiger Glyph. Jetzt über die Token ✓ 1,78:1 und 1,79:1 zur Seite, 1,32 und
262
+ 1,33:1 zur Card. Der Fehler-Glyph geht mit: #F08080 trägt auf der aufgehellten Füllung nur
263
+ ❌ 3,78:1, --c-error (#FFA5A5) ✓ 5,21:1. Analog --c-success (#5CE8A0) auf Grün 6,33:1.
264
+ (Light: helle Tints #E6F9F1 / #FDEAEA mit dunklem Glyph, kein Fix nötig.) */
265
+ [data-theme="dark"] .a11y-ok .a11y-rule-icon { background:var(--c-success-bg); color:var(--c-success) }
266
+ [data-theme="dark"] .a11y-fail .a11y-rule-icon { background:var(--c-error-bg); color:var(--c-error) }
267
+ /* Dark: buttons – Text/Rahmen auf die Bereichs-Light-Tints (--c-ink = -200/-100, wie t-Utilities,
268
+ Badges, Icons; auf der Skala) heben; Filled invertiert auf helle -300-Fläche + dunklen Text (s. u.). */
269
+ /* Filled: die dunkle -700/-800-Fläche verschwimmt im Dark mit bg-page (1,1–2,0:1, Button "verschwindet").
270
+ Daher invertieren: helle -300-Bereichsfläche + dunkler Text (n-900) → poppt als Primär-Aktion
271
+ (Fläche 3,6–8:1, Text 6–14:1). Nur .btn-filled umstellen (nicht --c500, das Tonal/Outlined/Text trägt);
272
+ .btn-on-band (weiße Fläche auf Bereichsband) ausnehmen. Light bleibt dunkle Fläche + weißer Text. */
273
+ [data-theme="dark"] .btn-filled:not(.btn-on-band) { color: var(--n-900) }
274
+ [data-theme="dark"] .btn-co.btn-filled:not(.btn-on-band) { background: var(--co-300) }
275
+ [data-theme="dark"] .btn-ki.btn-filled:not(.btn-on-band) { background: var(--ki-300) }
276
+ [data-theme="dark"] .btn-es.btn-filled:not(.btn-on-band) { background: var(--es-300) }
277
+ [data-theme="dark"] .btn-wo.btn-filled:not(.btn-on-band) { background: var(--wo-300) }
278
+ /* --c-ink = Bereichs-Light-Tint für Text/Rahmen der nicht-gefüllten Buttons im Dark. Dieselben Töne
279
+ wie t-Utilities, Badges, Icons, Eyebrows (auf der offiziellen Skala) statt eines off-scale color-mix → alle
280
+ Bereichstöne der Seite ziehen aus EINER Skala. */
281
+ [data-theme="dark"] .btn-co { --c-ink: var(--co-200) }
282
+ [data-theme="dark"] .btn-ki { --c-ink: var(--ki-200) }
283
+ [data-theme="dark"] .btn-es { --c-ink: var(--es-100) }
284
+ [data-theme="dark"] .btn-wo { --c-ink: var(--wo-200) }
285
+ /* Tonal im Dark: dezent brand-getönte Fläche (c500 18% in bg-page) + neutraler Rahmen über
286
+ --bd-strong-c (vorher als #9DA8B6 hartkodiert, dem alten --bd-strong-Wert; die Gleichung stimmte
287
+ nach der Flächen-Umstellung nicht mehr). Auf den vier Tonal-Füllungen 3,64:1 (ki) bis 4,87:1 (es),
288
+ also durchgehend über der 3:1-Schwelle. Der Rahmen macht den Button erkennbar, die Tönung
289
+ unterscheidet ihn von Outlined (brand-Rahmen). Basis bg-page (nicht bg-surface): so trägt der
290
+ -ink-Text (-200/-100) auch auf der Tonal-Fläche AA (≥5:1; auf bg-surface lagen co/wo bei
291
+ 4,43:1, knapp drunter). */
292
+ [data-theme="dark"] .btn-tonal {
293
+ background: color-mix(in srgb, var(--c500) 18%, var(--bg-page));
294
+ color: var(--c-ink);
295
+ border-color: var(--bd-strong-c);
296
+ }
297
+ [data-theme="dark"] .btn-elevated { color: var(--c-ink) }
298
+ [data-theme="dark"] .btn-outlined {
299
+ color: var(--c-ink);
300
+ border-color: var(--c-ink);
301
+ }
302
+ [data-theme="dark"] .btn-outlined:hover { background: color-mix(in srgb, var(--c50) 15%, var(--bg-surface)) }
303
+ [data-theme="dark"] .btn-text { color: var(--c-ink) }
304
+ [data-theme="dark"] .btn-text:hover { background: color-mix(in srgb, var(--c50) 15%, var(--bg-surface)) }
305
+
306
+ /* ════════════════════════════════════════════
307
+ DARK MODE: Beispielseiten
308
+ ════════════════════════════════════════════ */
309
+ /* Shared structural overrides */
310
+ /* .ds-card hat nur Rahmen, keinen Hintergrund (transparent → zeigt die Sektion durch). Im Dark zeigt
311
+ eine hintergrundlose Karte auf einer getönten Sektion denselben dunklen Ton → keine eigene Fläche.
312
+ Im Dark daher bg-surface geben: die Karte wird eine erkennbare, erhöhte Fläche. Karten MIT Inline-bg
313
+ (Info-Callouts auf co-50/n-50) behalten ihren Ton — Inline-Style schlägt diese Regel. */
314
+ [data-theme="dark"] .ds-card { background: var(--bg-surface) }
315
+ [data-theme="dark"] .ep-logo { color: var(--tx-primary) !important }
316
+ [data-theme="dark"] .ep-nav-links { color: var(--tx-secondary) !important }
317
+ /* Topnav Hover/Aktiv: co-700 (Light) → co-200 im Dark (co-700 wäre dunkel-auf-dunkel).
318
+ co-200 (#80DEDE) auf bg-surface bzw. co-50-dark ≥ 4.9:1 ✓ AA; Tönungsfläche bleibt co-50. */
319
+ [data-theme="dark"] .ep-nav-btn:hover,
320
+ [data-theme="dark"] .ep-nav-btn[aria-current="page"],
321
+ [data-theme="dark"] .ep-nav-has-sub:hover .ep-nav-item-toggle,
322
+ [data-theme="dark"] .ep-nav-has-sub.is-open .ep-nav-item-toggle,
323
+ [data-theme="dark"] .ep-nav-sub-btn:hover,
324
+ [data-theme="dark"] .ep-nav-sub-btn[aria-current="page"] { color: var(--co-200) }
325
+ /* Aktiv-Unterstrich im Dark ebenfalls co-200 (Light: co-700) — spiegelt die Aktiv-Textfarbe, 5,71:1 auf bg-surface. */
326
+ [data-theme="dark"] .ep-nav-btn::after { background: var(--co-200) }
327
+ /* Topnav-Aktionen (Suche/Theme): co-700-Hover wäre dunkel-auf-dunkel → co-200, wie die Nav-Links. */
328
+ [data-theme="dark"] .ep-nav-icon-btn:hover,
329
+ [data-theme="dark"] .ep-nav-search.is-open .ep-nav-search-toggle { color: var(--co-200) }
330
+ [data-theme="dark"] .ep-section { background: var(--bg-page) !important }
331
+ /* Section-Rhythmus erhalten: im Light staffeln sich Sektionen über bg-surface (Basis) und n-50
332
+ (Alternativ-Ton) — die „Abstufungen“. Pauschal alles auf bg-page macht den Dark flach. n-50-Sektionen
333
+ daher auf bg-surface heben (hellerer Dark-Surface-Tier, 1,22:1) → sichtbare Alternation Basis/erhöht. */
334
+ [data-theme="dark"] .ep-section[style*="var(--n-50)"] { background: var(--bg-surface) !important }
335
+ /* Die Hebung gilt AUSNAHMSLOS, auch für kartentragende Sektionen. Damit ist die Tonfolge im Dark
336
+ dieselbe wie im Light, und der Wechsel Basis/erhöht bleibt über die ganze Seite intakt.
337
+
338
+ Warum keine Ausnahme: Eine gehobene Sektion trifft den Ton ihrer eigenen bg-surface-Karten. Die
339
+ naheliegende Antwort war, solche Sektionen auf bg-page zurückzuziehen, damit die Karten die
340
+ hellere Stufe bilden. Das kostet aber genau den Rhythmus, um den es hier geht: die Sektion sitzt
341
+ dann auf dem Ton ihrer Nachbarn. Gemessen über die 24 Beispielseiten (133 Abschnitte): mit
342
+ Rücknahme 63 verschmolzene Übergänge, ohne 20, im Light sind es 17.
343
+
344
+ Die Karten lesen deshalb über ihren RAND, nicht über eine Tonstufe. Das ist keine Notlösung,
345
+ sondern exakt das, was im Light auf weißen Sektionen längst passiert: weiße Karte auf weißem
346
+ Grund, abgegrenzt durch die Kante. Die trägt im Light --bd-strong (2,25:1 gegen Weiß, 2,09:1
347
+ gegen eine n-50-Sektion), im Dark ist derselbe Rand mit 4,21:1 gegen die Kartenfläche noch
348
+ deutlicher, siehe die Rand-Regeln bei den Karten unten.
349
+ Auf bg-page-Sektionen bleibt es bei Tonstufe PLUS Rand. */
350
+ /* Getönte CTA-Sektionen: behalten im Dark ihren Bereichs-Tint (var(--XX-50) = gedämpfter Dunkston wie
351
+ #16302E), statt vom pauschalen bg-page geschluckt zu werden → CTA-Band bleibt als getönte Fläche
352
+ erkennbar. Texte/Labels darauf flippen auf helle Tints (8–10:1). */
353
+ /* Getönte Sektionen ziehen --XX-band statt --XX-50: das Band muss dunkler bleiben als die Karten
354
+ darauf, die kleine --XX-50-Füllung dagegen heller als ihr Grund. Siehe Token-Block oben. */
355
+ [data-theme="dark"] .ep-section[style*="var(--co-50)"] { background: var(--co-band) !important }
356
+ [data-theme="dark"] .ep-section[style*="var(--ki-50)"] { background: var(--ki-band) !important }
357
+ [data-theme="dark"] .ep-section[style*="var(--es-50)"] { background: var(--es-band) !important }
358
+ [data-theme="dark"] .ep-section[style*="var(--wo-50)"] { background: var(--wo-band) !important }
359
+ /* Header-Trennlinien: die getönten Beispielseiten-Header nutzen inline border-bottom mit dem hellen
360
+ Bereichston var(--XX-100). Der flippt nicht → im Dark eine grelle helle Linie (~7–11:1). Auf den
361
+ neutralen var(--bd) umstellen (~3–4:1), damit die Trennlinie dezent bleibt wie der gleichfarbige
362
+ Whisper im Light. Nur Sektionen mit border-bottom getroffen, nicht die randlosen getönten Bänder. */
363
+ [data-theme="dark"] .ep-section[style*="border-bottom:1px solid var(--co-100)"],
364
+ [data-theme="dark"] .ep-section[style*="border-bottom:1px solid var(--ki-100)"],
365
+ [data-theme="dark"] .ep-section[style*="border-bottom:1px solid var(--es-100)"],
366
+ [data-theme="dark"] .ep-section[style*="border-bottom:1px solid var(--wo-100)"] { border-bottom: var(--bd) !important }
367
+ [data-theme="dark"] .ep-section-h2 { color: var(--tx-primary) !important }
368
+ [data-theme="dark"] .ep-section-sub { color: var(--tx-secondary) !important }
369
+ /* Elevation = Interaktivität (siehe components.css): statische .ep-card ruhen flach — Containment über
370
+ die hellere bg-surface-Fläche + --bd-strong-Rahmen. Schatten nur für interaktive .ep-card-link. */
371
+ [data-theme="dark"] .ep-card { background: var(--bg-surface) !important }
372
+ [data-theme="dark"] .ep-card-link { box-shadow: var(--e2) }
373
+ /* Dark-only: Der Rand trägt die Kartenkante, weil die Karte auf einer gehobenen Sektion denselben
374
+ Ton hat wie ihr Grund (n-50-Sektionen werden im Dark auf bg-surface gehoben, siehe oben). Genau
375
+ wie im Light auf weißen Sektionen, dort übernimmt dieselbe --bd-strong-Kante (2,25:1).
376
+ Im Dark gibt --bd-strong-c 4,21:1 gegen die Kartenfläche, also noch klarer. .ep-card-link setzt in
377
+ components.css border-color:transparent, weil dort der Schatten allein trug; auf der tiefen
378
+ Dark-Basis trägt er das nicht mehr, gleiche Begründung wie bei den schwebenden Panels.
379
+ (Light: --bd-strong für .ep-card, transparenter Rand für die Link-Variante.) */
380
+ [data-theme="dark"] .ep-card,
381
+ [data-theme="dark"] .ep-card-link { border-color: var(--bd-strong-c) }
382
+ /* Dark-only: Auf der tieferen Seite tragen die schwarzen Schatten weniger als auf dem alten
383
+ #333E48. Der Hover hebt deshalb zusätzlich die Fläche (13,01:1 → 11,47:1), wie im
384
+ Material-Overlay-Modell, wo Tiefe primär über Helligkeit entsteht. Das ist ein Zustand,
385
+ KEINE dritte statische Flächen-Stufe. Das !important schlägt die .ep-card-Grundregel oben.
386
+ (Light: bg-surface-hover = bg-surface, dort trägt --e3 die Tiefe allein.) */
387
+ [data-theme="dark"] .ep-card-link:hover,
388
+ [data-theme="dark"] .ep-card-link:focus-visible { background: var(--bg-surface-hover) !important }
389
+ [data-theme="dark"] .ep-card-title { color: var(--tx-primary) !important }
390
+ [data-theme="dark"] .ep-card-text { color: var(--tx-secondary) !important }
391
+ /* ep-card-icon: Im Dark-Mode werden die --XX-50-Kacheln fast schwarz, die Glyph-Farben (--XX-700/800)
392
+ bleiben aber dunkel → dunkel-auf-dunkel (KI 2.2:1, ES 2.1:1, WO 2.5:1, Corp 3.4:1; der alte
393
+ filter:brightness(.75) verschlimmerte das auf bis zu 1.7:1). Glyph daher bereichsweise auf den
394
+ hellen --XX-100-Ton heben (nach der Flächen-Umstellung 7,49 bis 9,99:1, Schwelle für Icons ist 3:1).
395
+ CSS auf <svg> schlägt das Inline-stroke-Präsentationsattribut. */
396
+ [data-theme="dark"] .ep-card-icon[data-area="co"] svg { stroke: var(--co-100) }
397
+ /* Timeline-Marker: co-50-Tile wird im Dark dunkel → Icon auf helles co-100 heben */
398
+ [data-theme="dark"] .ep-tl-icon svg { stroke: var(--co-100) }
399
+ /* Der box-shadow-Ring stellt den Kreis von der Timeline-Linie frei und muss die Hintergrundfarbe
400
+ treffen. In Light = bg-surface (= weiß = Grund) → unsichtbar. Im Dark liegt die Timeline (Doku wie
401
+ ep-Section) auf bg-page; bg-surface waere dort ein hellerer Halo. Ring daher auf bg-page. */
402
+ [data-theme="dark"] .ep-tl-icon { box-shadow: 0 0 0 4px var(--bg-page) }
403
+ [data-theme="dark"] .ep-card-icon[data-area="ki"] svg { stroke: var(--ki-100) }
404
+ [data-theme="dark"] .ep-card-icon[data-area="es"] svg { stroke: var(--es-100) }
405
+ [data-theme="dark"] .ep-card-icon[data-area="wo"] svg { stroke: var(--wo-100) }
406
+ /* Gefüllte Brand-Glyphen (.ep-card-icon mit .t-*-Klasse, fill=currentColor) holen ihre Farbe schon
407
+ über t-* (flippt im Dark auf helle -200/-100). Der stroke-Override oben ist für OUTLINE-Icons; auf
408
+ gefüllten Pfaden erzwingt er eine zusätzliche 1,5px-Kontur → verzerrt den Glyph. Daher hier stroke:none. */
409
+ [data-theme="dark"] .ep-card-icon.t-co svg,
410
+ [data-theme="dark"] .ep-card-icon.t-ki svg,
411
+ [data-theme="dark"] .ep-card-icon.t-es svg,
412
+ [data-theme="dark"] .ep-card-icon.t-wo svg { stroke: none }
413
+ /* Offene Feature-Liste: --ki-800 bleibt im Dark-Mode dunkel-oliv, --ki-50 ist ein dunkler Olivton.
414
+ Pro-Glyph + Tier-Label daher auf das helle --ki-100 umstellen (>11:1 auf der Tile).
415
+ Core (tx-secondary/n-100) ist theme-aware und braucht keinen Override. */
416
+ [data-theme="dark"] .ep-feature-icon[data-area="ki"] { color: var(--ki-100) }
417
+ [data-theme="dark"] .ep-feature-icon[data-area="co"] { color: var(--co-100) }
418
+ [data-theme="dark"] .ep-feature-icon[data-area="es"] { color: var(--es-100) }
419
+ [data-theme="dark"] .ep-feature-icon[data-area="wo"] { color: var(--wo-100) }
420
+ /* Dark-only: .ep-compare nutzt rohes --ki-800 (flippt nicht) für Summary, ✓-Glyph und Pro-Header
421
+ → dunkel-auf-dunkel: ❌ ki-800 #475705 auf bg-page/ki-50 #2A3411. Auf helle ki-Töne heben ✓,
422
+ analog .ep-feature-icon/.ep-tier-label. (Light: ki-800/ki-900 bleiben.) */
423
+ [data-theme="dark"] .ep-compare-summary { color: var(--ki-200) }
424
+ [data-theme="dark"] .ep-compare-summary:hover { color: var(--ki-100) }
425
+ [data-theme="dark"] .ep-compare-yes { color: var(--ki-100) }
426
+ [data-theme="dark"] .ep-compare-table thead .ep-compare-pro { color: var(--ki-100) }
427
+ /* Testimonial-Zitatzeichen: --t-accent (-500) bei opacity .2 verschwindet im Dark auf der
428
+ bg-surface-Karte (perzeptuell schwach, es-500 zudem zu dunkel). Im Dark auf den helleren -300-Ton
429
+ + opacity .6 → erkennbarer, aber weiterhin dezenter Flourish (2,1–3,4:1, gleichmäßig über alle Bereiche). */
430
+ [data-theme="dark"] .testimonial-icon { color: var(--co-300); opacity: .6 }
431
+ [data-theme="dark"] .testimonial[data-area="ki"] .testimonial-icon { color: var(--ki-300) }
432
+ [data-theme="dark"] .testimonial[data-area="es"] .testimonial-icon { color: var(--es-300) }
433
+ [data-theme="dark"] .testimonial[data-area="wo"] .testimonial-icon { color: var(--wo-300) }
434
+ /* Blockquote-Zitatzeichen (.bq-icon): analog — -500 @ .35 verschwindet im Dark auf dem getönten
435
+ -50-Grund. Auf -300 je Bereich + opacity .6 → erkennbarer Flourish (2,7–4,5:1). */
436
+ [data-theme="dark"] .bq-icon { color: var(--co-300); opacity: .6 }
437
+ [data-theme="dark"] .bq[data-area="ki"] .bq-icon { color: var(--ki-300) }
438
+ [data-theme="dark"] .bq[data-area="es"] .bq-icon { color: var(--es-300) }
439
+ [data-theme="dark"] .bq[data-area="wo"] .bq-icon { color: var(--wo-300) }
440
+ /* Team-Stimme-Zitatzeichen (.team-voice-icon): gleicher Fall auf der bg-surface-Karte → -300 + opacity .6. */
441
+ [data-theme="dark"] .team-voice-icon { color: var(--co-300); opacity: .6 }
442
+ [data-theme="dark"] .team-voice[data-area="ki"] .team-voice-icon { color: var(--ki-300) }
443
+ [data-theme="dark"] .team-voice[data-area="es"] .team-voice-icon { color: var(--es-300) }
444
+ [data-theme="dark"] .team-voice[data-area="wo"] .team-voice-icon { color: var(--wo-300) }
445
+ /* Icon-Doku-Swatches (#sec-icons): dieselbe --XX-50-Kachel ist im Dark-Mode ein dunkler Bereichston, die
446
+ Glyph-Farben sind teils hart kodiert (#333E48, #004F4F, #183A0E), teils currentColor aus einer
447
+ inline gesetzten --XX-700/800-color → dunkel-auf-dunkel (analog .ep-card-icon). Glyph auf den
448
+ hellen --XX-100-Ton heben. Override pro <path> über Attribut-Selektor des Ist-Werts: schlägt
449
+ sowohl das Präsentationsattribut als auch die Inline-color am Container (sonst gewänne diese),
450
+ und trifft nur farbige Formen — Outline-Pfade mit fill="none" bleiben unberührt. Selektor auf
451
+ beliebige SVG-Form (nicht nur path): die Micro-16px-Icons nutzen <circle>/<rect>, die ein
452
+ path-Selektor verfehlt hätte (Knoten/Fenster blieben dunkel). */
453
+ [data-theme="dark"] .icon-size-swatch[data-area="co"] svg [fill="#333E48"],
454
+ [data-theme="dark"] .icon-size-swatch[data-area="co"] svg [fill="#004F4F"] { fill: var(--co-100) }
455
+ [data-theme="dark"] .icon-size-swatch[data-area="wo"] svg [stroke="#183A0E"] { stroke: var(--wo-100) }
456
+ [data-theme="dark"] .icon-size-swatch[data-area="wo"] svg [fill="currentColor"] { fill: var(--wo-100) }
457
+ [data-theme="dark"] .icon-size-swatch[data-area="ki"] svg [fill="currentColor"] { fill: var(--ki-100) }
458
+ [data-theme="dark"] .icon-size-swatch[data-area="es"] svg [fill="currentColor"] { fill: var(--es-100) }
459
+ [data-theme="dark"] .icon-size-swatch[data-area="es"] svg [stroke="currentColor"] { stroke: var(--es-100) }
460
+ /* Info-Callouts (.ds-card / Hinweisboxen auf --co-50-Grund): das dekorative co-700-Icon wird im Dark
461
+ dunkel-auf-dunkel (~3,35:1, knapp über der Grafik-Schwelle, aber schwach). Glyph auf --co-200 heben
462
+ (~11,8:1), konsistent mit den übrigen area-Glyphen. CSS schlägt das inline-stroke-Präsentationsattribut. */
463
+ [data-theme="dark"] [style*="var(--co-50)"] svg[stroke^="var(--co-"] { stroke: var(--co-200) }
464
+ [data-theme="dark"] [style*="var(--ki-50)"] svg[stroke^="var(--ki-"] { stroke: var(--ki-200) }
465
+ [data-theme="dark"] [style*="var(--es-50)"] svg[stroke^="var(--es-"] { stroke: var(--es-100) }
466
+ [data-theme="dark"] [style*="var(--wo-50)"] svg[stroke^="var(--wo-"] { stroke: var(--wo-200) }
467
+ /* Dark-only: Bereichs-Rahmen der Team-Stimme. Lag auf den -800-Stufen ❌ 1,07:1 (wo) bis 1,63:1 (ki)
468
+ gegen die Kartenfläche, der Rahmen war als Bereichssignal nicht vorhanden. Jetzt -300 wie beim
469
+ Bereichs-Chip ✓ 4,25:1 (es) bis 9,48:1 (ki), also über der 3:1-Schwelle für grafische Objekte.
470
+ Das Quote-Icon daneben ist dekorativ (opacity .6), der Rahmen trägt das Signal.
471
+ (Light: -600/-700/-500, 3,29 bis 5,66:1 auf Weiß.) */
472
+ [data-theme="dark"] .team-voice[data-area="co"] { border-color: var(--co-300) }
473
+ [data-theme="dark"] .team-voice[data-area="ki"] { border-color: var(--ki-300) }
474
+ [data-theme="dark"] .team-voice[data-area="es"] { border-color: var(--es-300) }
475
+ [data-theme="dark"] .team-voice[data-area="wo"] { border-color: var(--wo-300) }
476
+ [data-theme="dark"] .ep-tier-label[data-area="ki"] { color: var(--ki-100) }
477
+ [data-theme="dark"] .card-stat-strip { background: var(--bg-surface) }
478
+ [data-theme="dark"] .card-stat-flat[data-area="co"] .card-stat-flat-value { color: var(--co-200) }
479
+ [data-theme="dark"] .card-stat-flat[data-area="ki"] .card-stat-flat-value { color: var(--ki-200) }
480
+ [data-theme="dark"] .card-stat-flat[data-area="es"] .card-stat-flat-value { color: var(--es-100) }
481
+ [data-theme="dark"] .card-stat-flat[data-area="wo"] .card-stat-flat-value { color: var(--wo-200) }
482
+ /* In-Article-Callout-Eyebrow: 700er-/800er-Ton → dunkel-auf-dunkel auf der getönten -50-Fläche
483
+ (1,6–2,5:1). Auf die hellen Bereichs-Tints heben (8–10:1), wie bei .t-Utilities und Badges. Body-Text ist
484
+ tx-primary und flippt ohnehin. */
485
+ [data-theme="dark"] .article-callout-eyebrow { color: var(--co-200) }
486
+ [data-theme="dark"] .article-callout[data-area="ki"] .article-callout-eyebrow { color: var(--ki-200) }
487
+ [data-theme="dark"] .article-callout[data-area="es"] .article-callout-eyebrow { color: var(--es-100) }
488
+ [data-theme="dark"] .article-callout[data-area="wo"] .article-callout-eyebrow { color: var(--wo-200) }
489
+
490
+ /* ── Bereichs-Komponenten Vergleich ── */
491
+ /* Active tabs: --atab-color inline style is dark → override with light palette shades */
492
+ [data-theme="dark"] .atab[data-area="co"].active { color: var(--co-200); border-bottom-color: var(--co-200) }
493
+ [data-theme="dark"] .atab[data-area="ki"].active { color: var(--ki-200); border-bottom-color: var(--ki-200) }
494
+ [data-theme="dark"] .atab[data-area="es"].active { color: var(--es-100); border-bottom-color: var(--es-100) }
495
+ [data-theme="dark"] .atab[data-area="wo"].active { color: var(--wo-200); border-bottom-color: var(--wo-200) }
496
+ /* Branded chips: override inline color/border that are hardcoded dark palette shades */
497
+ [data-theme="dark"] #at-co .chip[style] { color: var(--co-200) !important; border-color: var(--co-300) !important }
498
+ [data-theme="dark"] #at-ai .chip[style] { color: var(--ki-200) !important; border-color: var(--ki-400) !important }
499
+ [data-theme="dark"] #at-es .chip[style] { color: var(--es-100) !important; border-color: var(--es-300) !important }
500
+ [data-theme="dark"] #at-wo .chip[style] { color: var(--wo-200) !important; border-color: var(--wo-300) !important }
501
+ /* Chip-Basis (nicht-inline, data-area): Text-/Border-Bereichstöne (--XX-700/800) bleiben im Dark dunkel
502
+ auf dem dunklen bg-surface → auf die hellen -200/-100/-300-Töne heben (analog .card-eyebrow). */
503
+ [data-theme="dark"] .chip[data-area="co"] { color: var(--co-200); border-color: var(--co-300) }
504
+ [data-theme="dark"] .chip[data-area="ki"] { color: var(--ki-200); border-color: var(--ki-400) }
505
+ [data-theme="dark"] .chip[data-area="es"] { color: var(--es-100); border-color: var(--es-300) }
506
+ [data-theme="dark"] .chip[data-area="wo"] { color: var(--wo-200); border-color: var(--wo-300) }
507
+ /* Dark-only: Der Hover-Rand nutzt im Light die kräftigeren -500/-600/-700-Töne. Im Dark sind das die
508
+ dunkleren, der Rand würde beim Überfahren also schwächer statt kräftiger — die Affordanz liefe
509
+ rückwärts (z.B. ki ruhend -400 #BEE82D → hover -700 #6B8208). Jeweils eine Stufe HELLER als der
510
+ Ruhezustand. (Light: -500/-600/-700 bleiben.) Spezifität 0,4,0 schlägt die Light-Regel. */
511
+ [data-theme="dark"] .chip[data-area="co"]:hover { border-color: var(--co-200) }
512
+ [data-theme="dark"] .chip[data-area="ki"]:hover { border-color: var(--ki-300) }
513
+ [data-theme="dark"] .chip[data-area="es"]:hover { border-color: var(--es-200) }
514
+ [data-theme="dark"] .chip[data-area="wo"]:hover { border-color: var(--wo-200) }
515
+ /* Doku-Sidebar: aktiver Eintrag hat im Light co-700-Text auf hellem co-50. Im Dark ist co-50 fast schwarz
516
+ (#16302E) → Text/Balken auf die hellen Töne heben (co-200 ~9,6:1 / co-300), sonst dunkel-auf-dunkel. */
517
+ [data-theme="dark"] .nav-item.active { color: var(--co-200); border-left-color: var(--co-300) }
518
+ /* Pills: --XX-50-Grund wird im Dark fast schwarz, Text --XX-700/800 bleibt dunkel → Text auf die hellen
519
+ -200/-100-Töne heben. Grund bleibt die dunkle -50-Kachel, der helle Text trägt den Kontrast (analog
520
+ .ep-card-icon/.card-eyebrow, ~13-15:1). aria-pressed-/Hover-States der Chips bleiben unberührt. */
521
+ [data-theme="dark"] .pill,
522
+ [data-theme="dark"] .pill[data-area="co"] { color: var(--co-200) }
523
+ [data-theme="dark"] .pill[data-area="ki"] { color: var(--ki-200) }
524
+ [data-theme="dark"] .pill[data-area="es"] { color: var(--es-100) }
525
+ [data-theme="dark"] .pill[data-area="wo"] { color: var(--wo-200) }
526
+ /* Bereichs-Text-Utilities + Bereichs-Badges: Light-Töne (-700/-800) bleiben im Dark dunkel → auf -200/-100 heben (Badge-Grund bleibt dunkle -50-Kachel, heller Text trägt den Kontrast). */
527
+ [data-theme="dark"] .t-ki { color: var(--ki-200) }
528
+ [data-theme="dark"] .t-es { color: var(--es-100) }
529
+ [data-theme="dark"] .t-wo { color: var(--wo-200) }
530
+ [data-theme="dark"] .badge[data-area="co"] { color: var(--co-200) }
531
+ [data-theme="dark"] .badge[data-area="ki"] { color: var(--ki-200) }
532
+ [data-theme="dark"] .badge[data-area="es"] { color: var(--es-100) }
533
+ [data-theme="dark"] .badge[data-area="wo"] { color: var(--wo-200) }
534
+
535
+ /* Segmented Control (dark): die dunkle -700/-800-Füllung würde auf dunklem Grund nicht heraustreten
536
+ → helle -300-Füllung mit dunklem -900-Text (Corporate: #4DD0D0 ~4,7:1 gg. inaktive Segmente,
537
+ Text ~9,9:1). Die Bereichs-Varianten brauchen eigene Dark-Regeln, weil [data-theme] .seg
538
+ spezifischer ist als .seg-ki allein und die Light-Variante sonst überschreiben würde. */
539
+ [data-theme="dark"] .seg { --seg-fill: var(--co-300); --seg-on: var(--co-900) }
540
+ [data-theme="dark"] .seg-ki { --seg-fill: var(--ki-300); --seg-on: var(--ki-900) }
541
+ [data-theme="dark"] .seg-es { --seg-fill: var(--es-300); --seg-on: var(--es-900) }
542
+ [data-theme="dark"] .seg-wo { --seg-fill: var(--wo-300); --seg-on: var(--wo-900) }
543
+
544
+ /* ── Spacing & Grid + Code tokens ── */
545
+ /* co-700 (#007575) auf co-50 (dark, #16302E) ~2,4:1 → co-300 (#4DD0D0) = 7,5:1 */
546
+ [data-theme="dark"] .gcol { color: var(--co-ink) } /* co-300 trug auf der gehobenen Fuellung nur 4,48:1, co-ink (co-200) 5,35:1 */
547
+ /* Dark-only: co-300 trug auf der gehobenen co-Fuellung nur noch 4,48:1. Ueber --co-ink (im Dark
548
+ co-200) sind es 5,35:1, und farbiger Text laeuft damit ueber dasselbe Token wie ueberall sonst. */
549
+ [data-theme="dark"] .token { color: var(--co-ink) }
550
+
551
+ /* Body-Link / Card-CTA-Link / t-co: --co-700 auf bg-page = 1.97:1 ❌ → --co-200 = 6.97:1 ✓ AA */
552
+ [data-theme="dark"] .body-link { color: var(--co-200) }
553
+ [data-theme="dark"] .body-link:hover { color: var(--co-100) }
554
+ [data-theme="dark"] .card-cta-link { color: var(--co-200) }
555
+ /* Bereichsvariante des Card-CTA-Links (Shades wie .ep-card-cta): hebt die Akzentfarbe auf den
556
+ hellen Bereichston, sonst dunkel-auf-dunkel. Höhere Spezifität als die co-200-Regel darüber. */
557
+ [data-theme="dark"] .card-cta-link[data-area="co"] { color: var(--co-200) }
558
+ [data-theme="dark"] .card-cta-link[data-area="ki"] { color: var(--ki-200) }
559
+ [data-theme="dark"] .card-cta-link[data-area="es"] { color: var(--es-100) }
560
+ [data-theme="dark"] .card-cta-link[data-area="wo"] { color: var(--wo-200) }
561
+ [data-theme="dark"] .t-co { color: var(--co-200) }
562
+ [data-theme="dark"] [data-accent="ki"] .t-co { color: var(--ki-200) }
563
+ [data-theme="dark"] [data-accent="es"] .t-co { color: var(--es-200) }
564
+ [data-theme="dark"] [data-accent="wo"] .t-co { color: var(--wo-200) }
565
+ [data-theme="dark"] [data-accent="ki"] .body-link { color: var(--ki-200) }
566
+ [data-theme="dark"] [data-accent="es"] .body-link { color: var(--es-200) }
567
+ [data-theme="dark"] [data-accent="wo"] .body-link { color: var(--wo-200) }
568
+ [data-theme="dark"] [data-accent] .footer .body-link { color: var(--co-200) }
569
+ [data-theme="dark"] [data-accent] .ep-topnav .t-co { color: var(--co-200) }
570
+ /* Dark-only: Hover der bereichsgetönten Body-Links. Light geht auf -800 (dunkler), im Dark ergäbe das
571
+ dunkel-auf-dunkel: ❌ wo-800 auf bg-page = 1,17:1 → wo-100 = 8,7:1 ✓. (Light: -800 bleibt.)
572
+ Nötig, weil die Light-Hover-Regel `[data-accent="wo"] .body-link:hover` dieselbe Spezifität hat wie
573
+ die Dark-Grundregel eine Zeile höher und components.css NACH dark-mode.css geladen wird — ohne
574
+ eigene :hover-Regel hier gewinnt sonst der Light-Wert. Analog zu .body-link:hover → co-100. */
575
+ [data-theme="dark"] [data-accent="ki"] .body-link:hover { color: var(--ki-100) }
576
+ [data-theme="dark"] [data-accent="es"] .body-link:hover { color: var(--es-100) }
577
+ [data-theme="dark"] [data-accent="wo"] .body-link:hover { color: var(--wo-100) }
578
+ /* Dark-only: derselbe Fall eine Regel weiter — der Chrome-Reset der Footer-Links auf area-getönten
579
+ Seiten. Light hebt den Hover auf co-800, im Dark ergibt das ❌ 1,97:1 auf dem Footer-Grund.
580
+ → co-100 ✓. (Light: co-800 bleibt.) Spezifität 0,5,0, damit die Ladereihenfolge egal ist. */
581
+ [data-theme="dark"] [data-accent] .footer .body-link:hover { color: var(--co-100) }
582
+ /* Dark-only: Hover-Zustände mit --co-700 auf theme-awarem tx-primary-Text (Footer-Link, Article-TOC)
583
+ → im Dark wäre der Hover dunkler statt heller: ❌ co-700 auf bg-page. Hover-Akzent auf --co-200 heben ✓,
584
+ analog .body-link:hover. (Light: co-700 bleibt.) */
585
+ [data-theme="dark"] .footer-link:hover { color: var(--co-200) }
586
+ [data-theme="dark"] .article-toc-summary:hover,
587
+ [data-theme="dark"] .article-toc-list a:hover { color: var(--co-200) }
588
+
589
+ /* ── Cards ── */
590
+ /* Dark-only: Kartenkante über den Rand, dieselbe Begründung wie bei .ep-card oben. Auf einer
591
+ gehobenen n-50-Sektion hat die Karte den Ton ihres Grundes, der Rand macht sie zur Fläche:
592
+ --bd-strong-c = 4,21:1 gegen die Karte. .card trägt --bd-strong inzwischen in beiden Modi, diese
593
+ Regel ist aber NICHT redundant: sie hält mit Spezifität 0,2,0 auch die Link-Karte, die im Light
594
+ border:none trägt und sich auf --e1 verlässt: auf der
595
+ tiefen Dark-Basis trägt der schwarze Schatten das nicht mehr. Spezifität 0,2,0 schlägt
596
+ a.card-elevated (0,1,1), die Ladereihenfolge spielt also keine Rolle.
597
+ box-sizing ist global border-box, der Rand ändert die Kartengröße nicht. */
598
+ [data-theme="dark"] .card { border: 1px solid var(--bd-strong-c) }
599
+ /* Area card icons/eyebrows – same shades used for area-specimen-text in dark mode.
600
+ Eyebrow-Text auf bg-surface, nachgemessen nach der Flächen-Umstellung:
601
+ co-200 (#80DEDE) 8,32:1 · ki-200 (#D6F06D) 10,25:1 · es-100 (#C8D9F5) 9,11:1 · wo-200 (#A3D48E) 7,66:1.
602
+ Dieselben Töne auf der getönten -50-Kachel (Icon-Glyph, Schwelle 3:1): 6,24 / 7,77 / 6,87 / 5,78:1. */
603
+ [data-theme="dark"] .card[data-area="co"] .card-media{color:var(--co-200)}
604
+ [data-theme="dark"] .card[data-area="ki"] .card-media{color:var(--ki-200)}
605
+ [data-theme="dark"] .card[data-area="es"] .card-media{color:var(--es-100)}
606
+ [data-theme="dark"] .card[data-area="wo"] .card-media{color:var(--wo-200)}
607
+ [data-theme="dark"] .card[data-area="co"] .card-eyebrow{color:var(--co-200)}
608
+ [data-theme="dark"] .card[data-area="ki"] .card-eyebrow{color:var(--ki-200)}
609
+ [data-theme="dark"] .card[data-area="es"] .card-eyebrow{color:var(--es-100)}
610
+ [data-theme="dark"] .card[data-area="wo"] .card-eyebrow{color:var(--wo-200)}
611
+ /* ep-card-Eyebrow + CTA-Link: nutzen area -700/-800 ohne Dark-Override → dunkel-auf-dunkel.
612
+ Auf die hellen -200/-100-Töne heben (wie .card-eyebrow). Default (ohne data-area) = co. */
613
+ [data-theme="dark"] .ep-card-eyebrow, [data-theme="dark"] .ep-card-cta { color: var(--co-200) }
614
+ /* co explizit data-area-scoped: components.css (laedt NACH dark-mode.css) hat
615
+ .ep-card[data-area="co"] .ep-card-cta{co-700} mit gleicher Spezifitaet (0,2,0) → gewinnt sonst per
616
+ Quellreihenfolge → CTA bliebe dunkel (1,62:1). Gleiche Spezifitaet wie ki/es/wo unten herstellen. */
617
+ [data-theme="dark"] .ep-card-eyebrow[data-area="co"], [data-theme="dark"] .ep-card[data-area="co"] .ep-card-cta { color: var(--co-200) }
618
+ [data-theme="dark"] .ep-card-eyebrow[data-area="ki"], [data-theme="dark"] .ep-card[data-area="ki"] .ep-card-cta { color: var(--ki-200) }
619
+ [data-theme="dark"] .ep-card-eyebrow[data-area="es"], [data-theme="dark"] .ep-card[data-area="es"] .ep-card-cta { color: var(--es-100) }
620
+ [data-theme="dark"] .ep-card-eyebrow[data-area="wo"], [data-theme="dark"] .ep-card[data-area="wo"] .ep-card-cta { color: var(--wo-200) }
621
+ /* Stat Card values: co-700 (#007575) ~1.6:1 on dark → lighter shades (verified ≥4.5:1) */
622
+ [data-theme="dark"] .card-stat[data-area="co"] .card-stat-value{color:var(--co-200)}
623
+ [data-theme="dark"] .card-stat[data-area="ki"] .card-stat-value{color:var(--ki-200)}
624
+ [data-theme="dark"] .card-stat[data-area="es"] .card-stat-value{color:var(--es-100)}
625
+ [data-theme="dark"] .card-stat[data-area="wo"] .card-stat-value{color:var(--wo-200)}
626
+
627
+ /* ── Area specimen text – lighter palette shades pass ≥4.5:1 on dark surface (#28323D) ── */
628
+ [data-theme="dark"] [data-area="co"] .area-specimen-text { color: var(--co-200) } /* #80DEDE · 4.92:1 */
629
+ [data-theme="dark"] [data-area="ki"] .area-specimen-text { color: var(--ki-200) } /* #D6F06D · 6.10:1 */
630
+ [data-theme="dark"] [data-area="es"] .area-specimen-text { color: var(--es-100) } /* #C8D9F5 · 5.41:1 */
631
+ [data-theme="dark"] [data-area="wo"] .area-specimen-text { color: var(--wo-200) } /* #A3D48E · 4.57:1 */
632
+
633
+ /* ── Download CTA (dark) ── */
634
+ /* Icon colors: area-50 wird sehr dunkel → helle Palette-Shades wie area-specimen-text */
635
+ [data-theme="dark"] .cta-dl[data-area="co"] .cta-dl-icon{color:var(--co-200)}
636
+ [data-theme="dark"] .cta-dl[data-area="ki"] .cta-dl-icon{color:var(--ki-200)}
637
+ [data-theme="dark"] .cta-dl[data-area="es"] .cta-dl-icon{color:var(--es-100)}
638
+ [data-theme="dark"] .cta-dl[data-area="wo"] .cta-dl-icon{color:var(--wo-200)}
639
+ [data-theme="dark"] .cta-dl[data-area="co"] .cta-dl-eyebrow{color:var(--co-200)}
640
+ [data-theme="dark"] .cta-dl[data-area="ki"] .cta-dl-eyebrow{color:var(--ki-200)}
641
+ [data-theme="dark"] .cta-dl[data-area="es"] .cta-dl-eyebrow{color:var(--es-100)}
642
+ [data-theme="dark"] .cta-dl[data-area="wo"] .cta-dl-eyebrow{color:var(--wo-200)}
643
+ [data-theme="dark"] .cta-strip[data-area="co"] .cta-strip-icon{color:var(--co-200)}
644
+ [data-theme="dark"] .cta-strip[data-area="ki"] .cta-strip-icon{color:var(--ki-200)}
645
+ [data-theme="dark"] .cta-strip[data-area="es"] .cta-strip-icon{color:var(--es-100)}
646
+ [data-theme="dark"] .cta-strip[data-area="wo"] .cta-strip-icon{color:var(--wo-200)}
647
+ [data-theme="dark"] .cta-visual[data-area="co"] .cta-visual-eyebrow{color:var(--co-200)}
648
+ [data-theme="dark"] .cta-visual[data-area="ki"] .cta-visual-eyebrow{color:var(--ki-200)}
649
+ [data-theme="dark"] .cta-visual[data-area="es"] .cta-visual-eyebrow{color:var(--es-100)}
650
+ [data-theme="dark"] .cta-visual[data-area="wo"] .cta-visual-eyebrow{color:var(--wo-200)}
651
+ [data-theme="dark"] .cta-link[data-area="co"]{color:var(--co-200)}
652
+ [data-theme="dark"] .cta-link[data-area="ki"]{color:var(--ki-200)}
653
+ [data-theme="dark"] .cta-link[data-area="es"]{color:var(--es-100)}
654
+ [data-theme="dark"] .cta-link[data-area="wo"]{color:var(--wo-200)}
655
+
656
+ /* ── Palette threshold badges (dark) ── */
657
+ [data-theme="dark"] .pal-thresholds{background:#0d1f3a;color:#90bcf0;border-color:#1e3f6b}
658
+ [data-theme="dark"] .thr-aa-l{background:#1a3355;color:#90bcf0}
659
+ [data-theme="dark"] .thr-aa{background:#0a3028;color:#80e8c8}
660
+ [data-theme="dark"] .thr-aaa{background:#2a1050;color:#c890ff}
661
+ /* Code-Block (hell → dunkel) */
662
+ [data-theme="dark"] .cb-wrap{border-color:var(--bd)}
663
+ [data-theme="dark"] .cb-header{background:var(--bg-page);border-bottom-color:var(--bd)}
664
+ [data-theme="dark"] .cb-lang{color:var(--co-200)}
665
+ [data-theme="dark"] .cb-copy{border-color:var(--bd);color:var(--tx-muted)}
666
+ [data-theme="dark"] .cb-copy:hover{background:var(--bg-overlay);color:var(--tx-primary)}
667
+ [data-theme="dark"] .cb-body{background:var(--bg-surface);color:var(--tx-primary)}
668
+ /* Syntax tokens auf bg-surface (#28323D), alle ≥4.5:1 verifiziert */
669
+ [data-theme="dark"] .cb-body .k{color:var(--es-200)} /* #98B7EE · 5.1:1 */
670
+ [data-theme="dark"] .cb-body .v{color:var(--co-200)} /* #80DEDE · 4.9:1 */
671
+ [data-theme="dark"] .cb-body .s{color:var(--wo-200)} /* #A3D48E · 4.6:1 */
672
+ /* .cb-body .c nutzt jetzt schon im Light var(--tx-muted), der Dark-Override wäre wirkungsgleich
673
+ und ist deshalb entfallen. Die Terminal-Variante hat ihre eigene Regel in components.css. */
674
+ [data-theme="dark"] .cb-body .fn{color:var(--ro-200)} /* #F0A0BE · 4.6:1 */
675
+ [data-theme="dark"] .cb-numbered .cb-ln::before{color:var(--tx-muted)}
676
+ /* Inline code – co-700 (#007575) ~1.6:1 auf co-50 dark → co-200 (#80DEDE) ~4.9:1 ✓ */
677
+ [data-theme="dark"] .cb-prose code{color:var(--co-200);border-color:var(--n-100)}
678
+ /* Tabellen-Header + Streifen: --n-50 flippt im Dark auf #0A1515 (fast schwarz) → harte schwarze
679
+ Balken auf dem dunklen bg-page-Grund (1,70:1). Auf bg-surface heben (1,22:1) = sanfte, hellere
680
+ Differenzierung statt schwarzer Balken. Spiegelt die dezente Light-Streifung (dort minimal dunkler). */
681
+ [data-theme="dark"] .tbl thead th { background: var(--bg-surface) }
682
+ [data-theme="dark"] .tbl--striped tbody tr:nth-child(even) td,
683
+ [data-theme="dark"] .tbl--striped tbody tr:nth-child(even) th { background: var(--bg-surface) }
684
+
685
+ /* ── Fotos im Dark dämpfen ──
686
+ Bisher gab es keine Behandlung: helle Fotos standen unverändert auf dem Seitengrund. Auf der
687
+ tieferen Fläche (17,51:1 statt 10,92:1) blendet ein großflächiges helles Bild deutlich stärker,
688
+ die Material-Guidance nennt das unter „große leuchtende Flächen begrenzen“. .92 ist bewusst
689
+ knapp gewählt: Markenfotos sollen nicht ausgewaschen wirken, es geht nur um die Spitzlichter.
690
+ Nicht zu verwechseln mit dem verworfenen filter:brightness(.75) auf Icon-Glyphen weiter oben.
691
+ Das betraf Strichgrafik auf getönten Kacheln und drückte den Kontrast auf 1,7:1; hier liegt
692
+ Bildinhalt vor, kein bedeutungstragender Vordergrund auf einer Fläche. */
693
+ [data-theme="dark"] .hero-image-media img,
694
+ [data-theme="dark"] .ep-media-band img,
695
+ [data-theme="dark"] .article-figure img { filter: brightness(.92) }
696
+
697
+ /* ── Schwebende Panels: der Rand übernimmt, was der Schatten nicht mehr trägt ──
698
+ Menüs und Popover grenzen sich im Light über --e3 vom Inhalt darunter ab. Auf der tiefen
699
+ Basisfläche trägt ein schwarzer Schatten das nicht mehr. Gemessen stand ein geöffnetes
700
+ Topnav-Menü über dem Hero-Foto nur noch 1,34:1 gegen die hellste Stelle daneben (vorher 1,92:1),
701
+ weil die Panel-Fläche mitgesunken ist, das Foto darunter aber nicht.
702
+ Eine dritte statische Flächen-Stufe wäre der Material-Weg („höher gleich heller“), würde aber die
703
+ Zwei-Stufen-Konvention des Systems brechen und einem Menü über einer Karte nur 1,13:1 bringen.
704
+ Stattdessen übernimmt der Rand: --bd-strong-c statt --bd-c, das ist unabhängig davon lesbar, was
705
+ zufällig hinter dem Panel liegt, und erfüllt WCAG 1.4.11 für die Panel-Grenze deutlich.
706
+ (Light: --bd bleibt, dort trägt der Schatten auf hellem Grund.) */
707
+ [data-theme="dark"] .ep-nav-sub,
708
+ [data-theme="dark"] .ep-select-menu,
709
+ [data-theme="dark"] .ep-combobox-menu,
710
+ [data-theme="dark"] .ep-nav-search-panel { border-color: var(--bd-strong-c) }
711
+ /* Die Snackbar gehört in dieselbe Familie: sie schwebt über beliebigem Inhalt und trägt im Light
712
+ keinen Rahmen, weil ihre dunkle Fläche auf hellem Grund für sich steht. Im Dark liegt sie mit
713
+ 1,23:1 (Default) bis 1,79:1 (Status) sehr nah am Grund, deshalb bekommt sie den Rand dazu.
714
+ Er trägt 4,61:1 auf der Default-Fläche und 3,17:1 auf den Status-Flächen. */
715
+ [data-theme="dark"] .snack { border: 1px solid var(--bd-strong-c) }
716
+ } /* Ende @media screen, umschließt die ganze Datei (siehe Kopf) */