@conciso/design-system-angular 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.
@@ -0,0 +1,3442 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { TemplateRef } from '@angular/core';
3
+ import { ControlValueAccessor } from '@angular/forms';
4
+ import * as _conciso_design_system_angular from '@conciso/design-system-angular';
5
+ import { SafeHtml } from '@angular/platform-browser';
6
+
7
+ /**
8
+ * Die vier Markenbereiche des Conciso Design Systems. Sie steuern in der CSS-Schicht
9
+ * die Bereichsfarben (Tokens --co-* / --ki-* / --es-* / --wo-*) und werden je nach
10
+ * Komponente entweder über eine Modifier-Klasse (z. B. .btn-co) oder ein
11
+ * data-area-Attribut (z. B. .badge[data-area="co"]) angewandt.
12
+ */
13
+ type CdsArea = 'co' | 'ki' | 'es' | 'wo';
14
+ declare const CDS_AREAS: CdsArea[];
15
+ declare const CDS_AREA_LABELS: Record<CdsArea, string>;
16
+
17
+ /** Drei Theme-Modi. „system“ folgt der OS-Einstellung (prefers-color-scheme). */
18
+ type CdsThemeMode = 'light' | 'dark' | 'system';
19
+ /** Reihenfolge (Cycle-Button, Segment, Dropdown). */
20
+ declare const CDS_THEME_ORDER: CdsThemeMode[];
21
+ /** Icon-Name je Modus. Registriert über die zentrale Icon-Registry (lib/icons/cds-icons);
22
+ * für diese drei Chrome-Icons hat das DS-Set kein eigenes Glyph → Heroicons. */
23
+ declare const CDS_THEME_ICON: Record<CdsThemeMode, string>;
24
+ /** Deutsches Label je Modus. */
25
+ declare const CDS_THEME_LABEL: Record<CdsThemeMode, string>;
26
+ /** tri = alle drei, binär = ohne „System“. Basis des `showSystem`-Parameters. */
27
+ declare function cdsThemeModes(showSystem: boolean): CdsThemeMode[];
28
+ declare const themeStore: {
29
+ /** Readonly-Signal des aktuellen Modus (Komponenten lesen hierüber). */
30
+ mode: _angular_core.Signal<CdsThemeMode>;
31
+ /** Setzen + anwenden + Abonnenten benachrichtigen (z. B. Toolbar-Sync). */
32
+ set(mode: CdsThemeMode): void;
33
+ /** Wie set(), aber OHNE Broadcast — für Toolbar→Store, um eine Emit-Rückkopplung
34
+ * zu vermeiden (die Toolbar hat den Wert ja bereits). */
35
+ setSilent(mode: CdsThemeMode): void;
36
+ /** Auf Modus-Änderungen hören (gibt eine Abmelde-Funktion zurück). */
37
+ subscribe(cb: (m: CdsThemeMode) => void): () => void;
38
+ };
39
+ /**
40
+ * Dünner Angular-Service über der modul-globalen Quelle — damit die Komponenten
41
+ * wie gewohnt `inject(ThemeModeService)` nutzen können. Setzt/entfernt letztlich
42
+ * `data-theme="dark"` am <html> (genau wie der DS es erwartet). Alle Switcher UND
43
+ * der globale Theme-Toolbar-Schalter bleiben so synchron.
44
+ */
45
+ declare class ThemeModeService {
46
+ readonly mode: _angular_core.Signal<CdsThemeMode>;
47
+ set(mode: CdsThemeMode): void;
48
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeModeService, never>;
49
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<any>;
50
+ }
51
+
52
+ /**
53
+ * Stil-Varianten des Buttons. `filled-on-band` ist der invertierte Filled-Button
54
+ * für farbige Bereichs-Bänder (Doku: „On-Band-Modifier“) — er wird hier als
55
+ * eigener Variant-Wert geführt statt als abhängiges Flag, da das Invertieren nur
56
+ * in Kombination mit `filled` je sinnvoll ist.
57
+ */
58
+ type CdsButtonVariant = 'filled' | 'tonal' | 'elevated' | 'outlined' | 'text' | 'filled-on-band';
59
+ type CdsButtonSize = 'sm' | 'md' | 'lg';
60
+ /**
61
+ * Button — dünner Angular-Wrapper um die bestehende `.btn`-CSS-Familie.
62
+ *
63
+ * Erfindet KEINE Styles: setzt ausschließlich die im Design System vorhandenen
64
+ * Klassen (.btn, .btn-filled/.btn-tonal/.btn-elevated/.btn-outlined/.btn-text,
65
+ * .btn-sm/.btn-lg, .btn-co/.btn-ki/.btn-es/.btn-wo, .btn-full, .btn-on-band)
66
+ * zusammen. Siehe css/components.css → „Buttons“. Der Klick wird als `clicked`
67
+ * ausgegeben (für Nutzung außerhalb reiner Formular-Submits).
68
+ */
69
+ declare class ButtonComponent {
70
+ /** Sichtbarer Text des Buttons. */
71
+ readonly label: _angular_core.InputSignal<string>;
72
+ /** Visuelle Variante → .btn-filled / .btn-tonal / .btn-elevated / .btn-outlined /
73
+ * .btn-text; `filled-on-band` → .btn-filled + .btn-on-band (invertiert). */
74
+ readonly variant: _angular_core.InputSignal<CdsButtonVariant>;
75
+ /** Markenbereich → .btn-co / .btn-ki / .btn-es / .btn-wo */
76
+ readonly area: _angular_core.InputSignal<CdsArea>;
77
+ /** Größe → .btn-sm / (md = Default) / .btn-lg */
78
+ readonly size: _angular_core.InputSignal<CdsButtonSize>;
79
+ /** Volle Breite → .btn-full (Host wird block, damit 100% greifen). */
80
+ readonly full: _angular_core.InputSignal<boolean>;
81
+ readonly disabled: _angular_core.InputSignal<boolean>;
82
+ readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
83
+ /** Klick auf den Button (feuert nicht, wenn `disabled`). */
84
+ readonly clicked: _angular_core.OutputEmitterRef<MouseEvent>;
85
+ /** @internal */
86
+ protected readonly classes: _angular_core.Signal<string>;
87
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ButtonComponent, never>;
88
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ButtonComponent, "cds-button", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "full": { "alias": "full"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; }, { "clicked": "clicked"; }, never, never, true, never>;
89
+ }
90
+
91
+ interface CdsNavSubItem {
92
+ label: string;
93
+ href: string;
94
+ }
95
+ interface CdsNavItem {
96
+ label: string;
97
+ href?: string;
98
+ sub?: CdsNavSubItem[];
99
+ }
100
+ /**
101
+ * Topnav — Wrapper um `.ep-topnav` aus css/components.css → „Topnav“.
102
+ *
103
+ * Customer-Navigation: Logo, Top-Level-Links mit optionalem Klapp-Submenü
104
+ * (.ep-nav-has-sub / .ep-nav-sub, aria-expanded), rechts gebündelte Aktionen
105
+ * (Such-Popover .ep-nav-search + Theme-Cycle-Button) und ein CTA-Button.
106
+ * Disclosure-Logik in Angular: nur ein Menü offen, Escape und Außenklick schließen.
107
+ *
108
+ * Der Theme-Umschalter ist fest der Cycle-Button (cds-theme-cycle); ob er auch
109
+ * „System“ anbietet, steuert `showSystemTheme` (durchgereicht an dessen showSystem).
110
+ */
111
+ declare class TopnavComponent {
112
+ private readonly host;
113
+ private readonly document;
114
+ private readonly uid;
115
+ /** @internal */
116
+ protected readonly searchId: string;
117
+ /** @internal */
118
+ protected readonly navId: string;
119
+ readonly logo: _angular_core.InputSignal<string>;
120
+ /** Optionales Logo-Bild/-Icon (URL oder Data-URI). Gesetzt → statt des Text-Logos.
121
+ * Doku: immer SVG (logo-conciso.svg), Default-Variante für helle Hintergründe. */
122
+ readonly logoSrc: _angular_core.InputSignal<string | undefined>;
123
+ /** Optionale helle Logo-Variante für den Dark Mode (Doku: logo-conciso-light.svg).
124
+ * Gesetzt → Theme-Swap via .logo-themed-* (schaltet über [data-theme] um);
125
+ * sonst wird logoSrc in beiden Themes gezeigt. */
126
+ readonly logoDarkSrc: _angular_core.InputSignal<string | undefined>;
127
+ /** Alt-Text des Logo-Bilds (Fallback: der Text aus `logo`). */
128
+ readonly logoAlt: _angular_core.InputSignal<string>;
129
+ readonly ctaLabel: _angular_core.InputSignal<string>;
130
+ /** Suche (Icon + Popover) rechts anzeigen. */
131
+ readonly showSearch: _angular_core.InputSignal<boolean>;
132
+ /** Kontakt-/CTA-Button anzeigen. */
133
+ readonly showCta: _angular_core.InputSignal<boolean>;
134
+ /** Bietet der Theme-Cycle-Button im Header auch „System“ an (tri) oder nur Hell/Dunkel? */
135
+ readonly showSystemTheme: _angular_core.InputSignal<boolean>;
136
+ /** Href des aktuell aktiven Eintrags (Single Source of Truth). Nur der Eintrag
137
+ * — Top-Level ODER Sub — mit passendem href erhält aria-current="page". Dadurch
138
+ * kann strukturell höchstens EINER aktiv sein (statt mehrerer current-Flags). */
139
+ readonly activeHref: _angular_core.InputSignal<string | undefined>;
140
+ readonly links: _angular_core.InputSignal<CdsNavItem[]>;
141
+ /** @internal */
142
+ protected readonly openIndex: _angular_core.WritableSignal<number>;
143
+ /** @internal */
144
+ protected readonly searchOpen: _angular_core.WritableSignal<boolean>;
145
+ /**
146
+ * Mobile-Menü offen? Schaltet .nav-open am Header (→ .ep-nav-links sichtbar).
147
+ *
148
+ * @internal
149
+ */
150
+ protected readonly navOpen: _angular_core.WritableSignal<boolean>;
151
+ /**
152
+ * Eindeutige ID des Submenüs zu Eintrag i (Toggle aria-controls ↔ .ep-nav-sub).
153
+ *
154
+ * @internal
155
+ */
156
+ protected subId(i: number): string;
157
+ /** @internal */
158
+ protected toggleSub(i: number): void;
159
+ /** @internal */
160
+ protected toggleSearch(): void;
161
+ /** @internal */
162
+ protected toggleNav(): void;
163
+ /** @internal */
164
+ protected closeAll(): void;
165
+ /** @internal */
166
+ protected onDocumentClick(event: MouseEvent): void;
167
+ /** @internal */
168
+ protected onEscape(): void;
169
+ /**
170
+ * Wie `closeAll()`, gibt den Fokus aber an den öffnenden Toggle zurück (Submenü-
171
+ * bzw. Such-Toggle) — NUR wenn der Fokus beim Schließen tatsächlich innerhalb des
172
+ * schließenden Bereichs lag. `css/components.css:1148` setzt `.ep-nav-sub{display:
173
+ * none}`, `:1189` dasselbe für `.ep-nav-search-pop`: das fokussierte Element
174
+ * verschwindet damit aus dem Fokus-Baum und der Fokus fiele sonst ans `<body>`
175
+ * (WCAG 2.4.3). Nur für den Escape-Pfad gedacht.
176
+ *
177
+ * @internal
178
+ */
179
+ private closeWithFocusReturn;
180
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TopnavComponent, never>;
181
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TopnavComponent, "cds-topnav", never, { "logo": { "alias": "logo"; "required": false; "isSignal": true; }; "logoSrc": { "alias": "logoSrc"; "required": false; "isSignal": true; }; "logoDarkSrc": { "alias": "logoDarkSrc"; "required": false; "isSignal": true; }; "logoAlt": { "alias": "logoAlt"; "required": false; "isSignal": true; }; "ctaLabel": { "alias": "ctaLabel"; "required": false; "isSignal": true; }; "showSearch": { "alias": "showSearch"; "required": false; "isSignal": true; }; "showCta": { "alias": "showCta"; "required": false; "isSignal": true; }; "showSystemTheme": { "alias": "showSystemTheme"; "required": false; "isSignal": true; }; "activeHref": { "alias": "activeHref"; "required": false; "isSignal": true; }; "links": { "alias": "links"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
182
+ }
183
+
184
+ /**
185
+ * Theme-Cycle-Button — ein einzelner Icon-Button (Stil `.ep-nav-icon-btn` aus der
186
+ * Topnav), der bei Klick durch die Modi zyklt. Das Icon zeigt den aktuellen Modus.
187
+ * Vorgesehener Einsatz: im Header. Icons über die zentrale Registry (lib/icons/cds-icons).
188
+ *
189
+ * `showSystem` schaltet zwischen tri (Hell→Dunkel→System) und binär (Hell→Dunkel).
190
+ */
191
+ declare class ThemeCycleComponent {
192
+ /** true → Hell/Dunkel/System, false → nur Hell/Dunkel. */
193
+ readonly showSystem: _angular_core.InputSignal<boolean>;
194
+ /** @internal */
195
+ protected readonly svc: ThemeModeService;
196
+ /** @internal */
197
+ protected readonly icon: _angular_core.Signal<string>;
198
+ /** @internal */
199
+ protected readonly label: _angular_core.Signal<string>;
200
+ /** @internal */
201
+ protected next(): void;
202
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeCycleComponent, never>;
203
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ThemeCycleComponent, "cds-theme-cycle", never, { "showSystem": { "alias": "showSystem"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
204
+ }
205
+
206
+ /**
207
+ * Bereichs-Badge — passive Bereichs-Kennzeichnung auf Basis von `.badge` +
208
+ * `[data-area]` aus css/components.css.
209
+ *
210
+ * Ordnet ein Element einer der vier Brand Areas zu (50er-Grund, 800er-Text).
211
+ * Nicht interaktiv. Für Zustände die Status-Badge, für einen redaktionellen
212
+ * Anker im Lesefluss die Pill nutzen; für interaktive Filter den Chip.
213
+ */
214
+ declare class AreaBadgeComponent {
215
+ /** Sichtbarer Text der Badge. */
216
+ readonly label: _angular_core.InputSignal<string>;
217
+ /** Brand Area → data-area (bestimmt die Bereichsfarbe). */
218
+ readonly area: _angular_core.InputSignal<CdsArea>;
219
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AreaBadgeComponent, never>;
220
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AreaBadgeComponent, "cds-area-badge", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
221
+ }
222
+
223
+ /** Status-Töne der Badge-Klassen (.badge-ok / .badge-warn / .badge-err / .badge-neu). */
224
+ type CdsBadgeTone = 'ok' | 'warn' | 'err' | 'neu';
225
+ /**
226
+ * Status-Badge — passive Zustands-Kennzeichnung auf Basis von `.badge` +
227
+ * `.badge-{ok|warn|err|neu}` aus css/components.css.
228
+ *
229
+ * Trägt einen Zustand über semantische Farben (OK, Warnung, Fehler, Neutral) —
230
+ * z. B. „Live“, „Beta“, „Deprecated“, „Draft“. Nicht interaktiv. Für die
231
+ * Zuordnung zu einer Brand Area die Bereichs-Badge, für einen redaktionellen
232
+ * Anker im Lesefluss die Pill nutzen; für interaktive Filter den Chip.
233
+ */
234
+ declare class StatusBadgeComponent {
235
+ /** Sichtbarer Text der Badge. */
236
+ readonly label: _angular_core.InputSignal<string>;
237
+ /** Status-Ton → semantische Farbe. */
238
+ readonly tone: _angular_core.InputSignal<CdsBadgeTone>;
239
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatusBadgeComponent, never>;
240
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatusBadgeComponent, "cds-status-badge", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
241
+ }
242
+
243
+ /**
244
+ * Chip — Wrapper um `.chip` aus css/components.css → „Badges & Chips“.
245
+ *
246
+ * Interaktiver Filter-Chip auf Basis von `aria-pressed` (.chip[aria-pressed],
247
+ * optional area-aware über [data-area]). Klick schaltet den Zustand um.
248
+ *
249
+ * Chips sind interaktive Elemente (Filter/Einstellungen), KEINE statischen Tags.
250
+ * Für nicht-interaktive Bereichs-Labels die Badge- bzw. Pill-Komponente nutzen.
251
+ */
252
+ declare class ChipComponent {
253
+ /** Sichtbarer Text des Chips. */
254
+ readonly label: _angular_core.InputSignal<string>;
255
+ /** Markenbereich → data-area (area-aware Outline). */
256
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
257
+ /** Gedrückt/aktiv → aria-pressed. Two-Way (`[(pressed)]`) + pressedChange via model(). */
258
+ readonly pressed: _angular_core.ModelSignal<boolean>;
259
+ /** @internal */
260
+ protected toggle(): void;
261
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChipComponent, never>;
262
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChipComponent, "cds-chip", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "pressed": { "alias": "pressed"; "required": false; "isSignal": true; }; }, { "pressed": "pressedChange"; }, never, never, true, never>;
263
+ }
264
+
265
+ /**
266
+ * Pill — Wrapper um `.pill` aus css/components.css → „Badges & Chips“ (Pill).
267
+ *
268
+ * Passive, redaktionelle Bereichs-Markierung, typografisch als Eyebrow (uppercase,
269
+ * letter-spacing .09em, label-xs) — sitzt typischerweise oberhalb eines Titels und
270
+ * ordnet einen Inhalt einer Brand Area zu. Abgrenzung zur Badge: die Pill ist der
271
+ * thematische „Was für ein Inhalt ist das?“-Anker im Lesefluss; die Badge die
272
+ * punktuelle Status-/Bereichs-Kennzeichnung neben Elementen. Nicht interaktiv.
273
+ *
274
+ * a11y: Der reine Bereichsname klingt im Screenreader-Fluss leicht wie eine
275
+ * Überschrift — daher trägt die Pill ein explizites `aria-label` (Default
276
+ * „Bereich <label>“, überschreibbar), genau wie in der Doku vorgegeben.
277
+ */
278
+ declare class PillComponent {
279
+ /** Sichtbarer Bereichsname. */
280
+ readonly label: _angular_core.InputSignal<string>;
281
+ /** Brand Area → data-area (Farbton; ohne Angabe greift der Corporate-Default). */
282
+ readonly area: _angular_core.InputSignal<CdsArea>;
283
+ /** aria-label überschreiben; Default „Bereich <label>“. */
284
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
285
+ /** @internal */
286
+ protected readonly computedAriaLabel: _angular_core.Signal<string>;
287
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PillComponent, never>;
288
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PillComponent, "cds-pill", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
289
+ }
290
+
291
+ /**
292
+ * ControlValueAccessor-Kitt OHNE Markup- oder Werttyp-Annahmen: hält NUR, was bei
293
+ * `checkbox`, `radio-group`, `slider`, `scale` (und, über `FieldBase`, den drei
294
+ * Field-Komponenten) wortgleich war — die `onChange`/`onTouched`-Callbacks plus
295
+ * `writeValue`, `registerOnChange`, `registerOnTouched`, `setDisabledState`.
296
+ *
297
+ * Generisch über den Werttyp `T` (boolean bei Checkbox, string bei RadioGroup/
298
+ * FieldBase, number bei Slider/Scale). Die defensive Normalisierung eines
299
+ * eingehenden Formularwerts (Klemmen auf [min, max], `!!`-Cast, `NaN`-Abfang, …)
300
+ * ist komponentenspezifisch und bleibt darum bewusst NICHT hier: `writeValue` ruft
301
+ * den überschreibbaren Hook `normalizeValue` auf (Default: unverändert), die
302
+ * konkrete Komponente überschreibt ihn UND `applyValue`/`applyDisabled` (schreiben
303
+ * in ihr eigenes `model()`-Signal — die Basis kennt dessen Namen nicht).
304
+ */
305
+ declare abstract class CvaBase<T> implements ControlValueAccessor {
306
+ /** @internal */
307
+ protected onChange: (value: T) => void;
308
+ /** @internal */
309
+ protected onTouched: () => void;
310
+ /**
311
+ * Rohen Formularwert in einen gültigen Komponentenwert übersetzen (Klemmen,
312
+ * Typ-Cast, `NaN`-Abfang, …). Default: unverändert durchreichen.
313
+ *
314
+ * @internal
315
+ */
316
+ protected normalizeValue(value: T): T;
317
+ /** Normalisierten Wert ins eigene `model()`-Signal der Komponente schreiben. @internal */
318
+ protected abstract applyValue(value: T): void;
319
+ /** `disabled`-Zustand ins eigene `model()`-Signal der Komponente schreiben. @internal */
320
+ protected abstract applyDisabled(disabled: boolean): void;
321
+ /** @internal */
322
+ writeValue(value: T): void;
323
+ /** @internal */
324
+ registerOnChange(fn: (value: T) => void): void;
325
+ /** @internal */
326
+ registerOnTouched(fn: () => void): void;
327
+ /** @internal */
328
+ setDisabledState(isDisabled: boolean): void;
329
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CvaBase<any>, never>;
330
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<CvaBase<any>, never, never, {}, {}, never, never, true, never>;
331
+ }
332
+
333
+ /**
334
+ * Gemeinsame Basis der Field-Komponenten (Textfeld / Textbereich / Auswahlfeld).
335
+ *
336
+ * Bündelt die geteilten Inputs, die a11y-Verdrahtung UND die Wert-Anbindung. Als
337
+ * `ControlValueAccessor` binden sich die Felder direkt an Angular-Formulare
338
+ * (`[(ngModel)]`, `formControlName`) — der übliche Weg für eine Komponenten-
339
+ * bibliothek. Zusätzlich ist `value` ein `model()`, sodass ohne Formular auch
340
+ * `[(value)]` und der `valueChange`-Output funktionieren. Den ControlValueAccessor-
341
+ * Kitt (onChange/onTouched, writeValue, registerOnChange/-Touched, setDisabledState)
342
+ * erbt sie von `CvaBase` (`lib/shared/cva-base.directive.ts`) — geteilt mit
343
+ * Checkbox/RadioGroup/Slider/Scale, die dieselbe Boilerplate wortgleich hatten.
344
+ *
345
+ * Angular vererbt Inputs/Logik über eine mit `@Directive()` dekorierte abstrakte
346
+ * Basisklasse — deshalb steht die LOGIK hier. Das gemeinsame MARKUP (Label/Helper/
347
+ * Fehler) wird NICHT vererbt (Angular vererbt keine Templates); dafür teilen sich
348
+ * die Komponenten die FieldShellComponent per Komposition. Den `NG_VALUE_ACCESSOR`-
349
+ * Provider setzt jede konkrete Komponente selbst (forwardRef auf ihre Klasse).
350
+ */
351
+ declare abstract class FieldBase extends CvaBase<string> {
352
+ /** Sichtbares Label. */
353
+ readonly label: _angular_core.InputSignal<string>;
354
+ /** Optionaler Hilfetext unter dem Feld. */
355
+ readonly helper: _angular_core.InputSignal<string>;
356
+ /** Gesetzt = Fehlerzustand (.has-error + .error-msg). */
357
+ readonly error: _angular_core.InputSignal<string>;
358
+ /** Pflichtfeld → .req-Asterisk + aria-required. */
359
+ readonly required: _angular_core.InputSignal<boolean>;
360
+ /** id für die label/for- und aria-describedby-Verknüpfung. Default eindeutig. */
361
+ readonly fieldId: _angular_core.InputSignal<string>;
362
+ /** Feldwert — Two-Way (`[(value)]`) UND Angular-Forms (ngModel/formControlName). */
363
+ readonly value: _angular_core.ModelSignal<string>;
364
+ /** Deaktiviert; auch über Angular-Forms (setDisabledState) steuerbar. */
365
+ readonly disabled: _angular_core.ModelSignal<boolean>;
366
+ /** @internal */
367
+ protected normalizeValue(value: string): string;
368
+ /** @internal */
369
+ protected applyValue(value: string): void;
370
+ /** @internal */
371
+ protected applyDisabled(disabled: boolean): void;
372
+ /**
373
+ * Vom Template bei Eingabe/Änderung des nativen Controls aufgerufen.
374
+ *
375
+ * @internal
376
+ */
377
+ protected handleInput(event: Event): void;
378
+ /**
379
+ * Vom Template bei Verlassen des Felds → markiert das Control als „touched“.
380
+ *
381
+ * @internal
382
+ */
383
+ protected handleBlur(): void;
384
+ /** @internal */
385
+ protected readonly errorId: _angular_core.Signal<string>;
386
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FieldBase, never>;
387
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<FieldBase, never, never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "helper": { "alias": "helper"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "fieldId": { "alias": "fieldId"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "disabled": "disabledChange"; }, never, never, true, never>;
388
+ }
389
+
390
+ /**
391
+ * Textfeld — einzeiliges `<input>` im `.field`-Gerüst (E-Mail, Text, Tel, … über
392
+ * `type`). Pflichtfelder tragen aria-required; im Fehlerzustand wird die Meldung
393
+ * über aria-describedby/aria-invalid verknüpft — wie docs/index.html.
394
+ *
395
+ * Als `ControlValueAccessor` (siehe FieldBase) direkt an Angular-Formulare
396
+ * anbindbar (`[(ngModel)]`, `formControlName`) bzw. ohne Formular per `[(value)]`.
397
+ */
398
+ declare class TextFieldComponent extends FieldBase {
399
+ /** input[type] (text, email, tel, …). */
400
+ readonly type: _angular_core.InputSignal<string>;
401
+ readonly placeholder: _angular_core.InputSignal<string>;
402
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TextFieldComponent, never>;
403
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TextFieldComponent, "cds-text-field", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
404
+ }
405
+
406
+ /**
407
+ * Textbereich — mehrzeiliges `<textarea>` im `.field`-Gerüst. Gleiche a11y-
408
+ * Verdrahtung wie das Textfeld (aria-required/-invalid/-describedby).
409
+ *
410
+ * Als `ControlValueAccessor` (siehe FieldBase) direkt an Angular-Formulare
411
+ * anbindbar (`[(ngModel)]`, `formControlName`) bzw. ohne Formular per `[(value)]`.
412
+ */
413
+ declare class TextareaFieldComponent extends FieldBase {
414
+ readonly placeholder: _angular_core.InputSignal<string>;
415
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TextareaFieldComponent, never>;
416
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TextareaFieldComponent, "cds-textarea-field", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
417
+ }
418
+
419
+ /**
420
+ * Auswahlfeld — `<select>` im `.field`-Gerüst. Die Optionen kommen über `options`;
421
+ * a11y-Verdrahtung wie beim Textfeld (aria-required/-invalid/-describedby).
422
+ *
423
+ * Als `ControlValueAccessor` (siehe FieldBase) direkt an Angular-Formulare
424
+ * anbindbar (`[(ngModel)]`, `formControlName`) bzw. ohne Formular per `[(value)]`.
425
+ */
426
+ declare class SelectFieldComponent extends FieldBase {
427
+ /** Auswahloptionen (erste dient üblicherweise als Platzhalter, z. B. „Bitte wählen“). */
428
+ readonly options: _angular_core.InputSignal<string[]>;
429
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SelectFieldComponent, never>;
430
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SelectFieldComponent, "cds-select-field", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
431
+ }
432
+
433
+ /**
434
+ * Checkbox — Einwilligungs-/Consent-Feld nach docs/index.html („Forms“).
435
+ *
436
+ * Bewusst KEIN nachgebautes Kästchen: ein natives `<input type="checkbox">` mit
437
+ * `accent-color` in der Bereichsfarbe (genau wie die Doku), umschlossen von einem
438
+ * `<label>` mit dem Einwilligungstext und optional verlinktem Datenschutzhinweis.
439
+ * Dokumentierte Verwendung: Newsletter-/DSGVO-Einwilligung, i. d. R. `required`.
440
+ *
441
+ * Als `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,
442
+ * `formControlName`); ohne Formular geht `[(checked)]` (checkedChange via model()).
443
+ */
444
+ declare class CheckboxComponent extends CvaBase<boolean> {
445
+ /** Einwilligungstext neben der Checkbox. */
446
+ readonly label: _angular_core.InputSignal<string>;
447
+ /** Optionaler verlinkter Hinweis am Ende des Labels (z. B. „Datenschutzhinweise“). */
448
+ readonly linkLabel: _angular_core.InputSignal<string>;
449
+ /** Ziel des verlinkten Hinweises. */
450
+ readonly linkHref: _angular_core.InputSignal<string>;
451
+ /** Pflicht-Einwilligung → required + aria-required + .req-Sternchen am Label-Ende. */
452
+ readonly required: _angular_core.InputSignal<boolean>;
453
+ /** Gesetzt/aktiv → checked. Two-Way (`[(checked)]`) UND Angular-Forms. */
454
+ readonly checked: _angular_core.ModelSignal<boolean>;
455
+ /** Deaktiviert; auch über Angular-Forms (setDisabledState) steuerbar. */
456
+ readonly disabled: _angular_core.ModelSignal<boolean>;
457
+ /** Brand Area → accent-color der Checkbox. */
458
+ readonly area: _angular_core.InputSignal<CdsArea>;
459
+ /** @internal */
460
+ protected normalizeValue(value: boolean): boolean;
461
+ /** @internal */
462
+ protected applyValue(value: boolean): void;
463
+ /** @internal */
464
+ protected applyDisabled(disabled: boolean): void;
465
+ /** @internal */
466
+ protected onCheckboxChange(event: Event): void;
467
+ /** @internal */
468
+ protected markTouched(): void;
469
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CheckboxComponent, never>;
470
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CheckboxComponent, "cds-checkbox", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "linkLabel": { "alias": "linkLabel"; "required": false; "isSignal": true; }; "linkHref": { "alias": "linkHref"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "disabled": "disabledChange"; }, never, never, true, never>;
471
+ }
472
+
473
+ /**
474
+ * Radio-Gruppe (Optionsfelder) nach docs/index.html („Forms“).
475
+ *
476
+ * Für 2–6 sich gegenseitig ausschließende Optionen (mehr → Select). Bewusst KEIN
477
+ * nachgebauter Kreis: native `<input type="radio">` mit `accent-color` in der
478
+ * Bereichsfarbe, gruppiert in `<fieldset>`/`<legend>` (Gruppen-Label wie ein
479
+ * Feld-Label), alle Optionen teilen denselben `name`.
480
+ *
481
+ * Als `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,
482
+ * `formControlName`); ohne Formular geht `[(value)]` (valueChange via model()).
483
+ */
484
+ declare class RadioGroupComponent extends CvaBase<string> {
485
+ /** Gruppen-Label (die Frage) → <legend>. */
486
+ readonly legend: _angular_core.InputSignal<string>;
487
+ /** Auswahloptionen (Label = Wert). */
488
+ readonly options: _angular_core.InputSignal<string[]>;
489
+ /** Aktuell gewählter Wert. Two-Way (`[(value)]`) UND Angular-Forms. */
490
+ readonly value: _angular_core.ModelSignal<string>;
491
+ /** Gemeinsamer name aller Radios der Gruppe. Default eindeutig. */
492
+ readonly name: _angular_core.InputSignal<string>;
493
+ /** Pflichtauswahl → required + .req-Asterisk. */
494
+ readonly required: _angular_core.InputSignal<boolean>;
495
+ /** Deaktiviert; auch über Angular-Forms (setDisabledState) steuerbar. */
496
+ readonly disabled: _angular_core.ModelSignal<boolean>;
497
+ /** Brand Area → accent-color der Radios. */
498
+ readonly area: _angular_core.InputSignal<CdsArea>;
499
+ /** @internal */
500
+ protected normalizeValue(value: string): string;
501
+ /** @internal */
502
+ protected applyValue(value: string): void;
503
+ /** @internal */
504
+ protected applyDisabled(disabled: boolean): void;
505
+ /** @internal */
506
+ protected onRadioChange(opt: string): void;
507
+ /** @internal */
508
+ protected markTouched(): void;
509
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<RadioGroupComponent, never>;
510
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<RadioGroupComponent, "cds-radio-group", never, { "legend": { "alias": "legend"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "disabled": "disabledChange"; }, never, never, true, never>;
511
+ }
512
+
513
+ interface CdsSelectOption {
514
+ value: string;
515
+ label: string;
516
+ }
517
+ /**
518
+ * Custom Select (cds-select) — gestylte Einzelauswahl über `.ep-select` aus
519
+ * css/components.css → Doku „Dropdowns“.
520
+ *
521
+ * Trigger-Button + Listbox-Popup mit Häkchen und Bereichs-Akzent (data-area).
522
+ * Anders als die dünnen Wrapper trägt diese Komponente das Verhalten selbst — das
523
+ * ist ihr Zweck (das native <select> reicht dafür nicht): volle Tastatur (↑↓,
524
+ * Pos1/Ende, Type-ahead, Enter wählt, Esc schließt) und die dokumentierte a11y
525
+ * (role=listbox/option, aria-haspopup, aria-expanded, aria-activedescendant,
526
+ * aria-selected). Für kurze Listen in Formularen bleibt das native cds-select-field
527
+ * der Standard; dies hier ist für bereichs-akzentuierte Auswahl.
528
+ *
529
+ * Als `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,
530
+ * `formControlName`); ohne Formular geht `[(value)]` (valueChange via model()).
531
+ */
532
+ declare class SelectComponent implements ControlValueAccessor {
533
+ private readonly host;
534
+ private readonly trigger;
535
+ private readonly menu;
536
+ readonly label: _angular_core.InputSignal<string>;
537
+ readonly options: _angular_core.InputSignal<CdsSelectOption[]>;
538
+ /** Aktuell gewählter Wert (value der Option). Two-Way (`[(value)]`) UND Angular-Forms. */
539
+ readonly value: _angular_core.ModelSignal<string | undefined>;
540
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
541
+ readonly placeholder: _angular_core.InputSignal<string>;
542
+ /** Deaktiviert; auch über Angular-Forms (setDisabledState) steuerbar. */
543
+ readonly disabled: _angular_core.ModelSignal<boolean>;
544
+ /** Optionaler Feldname → verstecktes Input für den Formular-Submit. */
545
+ readonly name: _angular_core.InputSignal<string | undefined>;
546
+ /** @internal */
547
+ protected readonly open: _angular_core.WritableSignal<boolean>;
548
+ /** @internal */
549
+ protected readonly activeIndex: _angular_core.WritableSignal<number>;
550
+ private onChange;
551
+ private onTouched;
552
+ /** @internal */
553
+ writeValue(value: string | null): void;
554
+ /** @internal */
555
+ registerOnChange(fn: (value: string) => void): void;
556
+ /** @internal */
557
+ registerOnTouched(fn: () => void): void;
558
+ /** @internal */
559
+ setDisabledState(isDisabled: boolean): void;
560
+ private readonly instance;
561
+ /** @internal */
562
+ protected readonly ids: {
563
+ label: string;
564
+ value: string;
565
+ menu: string;
566
+ option: (i: number) => string;
567
+ };
568
+ private typeBuffer;
569
+ private readonly menuFocusTimer;
570
+ private readonly scrollTimer;
571
+ private readonly typeaheadTimer;
572
+ /** @internal */
573
+ protected selectedOption(): CdsSelectOption | undefined;
574
+ /** @internal */
575
+ protected toggle(): void;
576
+ private openMenu;
577
+ /** @internal */
578
+ protected close(focusTrigger?: boolean): void;
579
+ /** @internal */
580
+ protected select(i: number): void;
581
+ /** @internal */
582
+ protected markTouched(): void;
583
+ /**
584
+ * `onTouched` erst, wenn der Fokus die GESAMTE Komponente verlässt — nicht schon beim
585
+ * Öffnen, wenn er vom Trigger in die Listbox wandert (beides liegt im Host). Sonst
586
+ * wäre das Control „touched“, bevor überhaupt ausgewählt wurde.
587
+ *
588
+ * @internal
589
+ */
590
+ protected onFocusOut(event: FocusEvent): void;
591
+ /**
592
+ * Tastatur am Trigger-Button: nur Öffnen (im offenen Zustand hat die Listbox Fokus).
593
+ *
594
+ * @internal
595
+ */
596
+ protected onTriggerKeydown(event: KeyboardEvent): void;
597
+ /**
598
+ * Tastatur in der offenen Listbox: Navigation, Auswahl, Schließen, Type-ahead.
599
+ *
600
+ * @internal
601
+ */
602
+ protected onMenuKeydown(event: KeyboardEvent): void;
603
+ private move;
604
+ private setActive;
605
+ private typeahead;
606
+ /** @internal */
607
+ protected onDocPointerDown(event: PointerEvent): void;
608
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SelectComponent, never>;
609
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SelectComponent, "cds-select", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "disabled": "disabledChange"; }, never, never, true, never>;
610
+ }
611
+
612
+ /**
613
+ * Combobox (cds-combobox) — Tipp-Filter über `.ep-combobox` aus css/components.css
614
+ * → Doku „Dropdowns“. Wie der Custom Select, aber mit Substring-Filter im Feld (für
615
+ * lange Listen). Optional Multi-Select mit Chips (`multi`).
616
+ *
617
+ * Verhalten/a11y selbst getragen: Input mit role=combobox (dort ist
618
+ * aria-activedescendant erlaubt), aria-expanded/-controls/-autocomplete; Listbox mit
619
+ * role=listbox/option; ↓ öffnet/navigiert, Enter wählt, Esc schließt, Rücktaste bei
620
+ * leerem Feld entfernt im Multi-Modus den letzten Chip. Beim Schließen ohne Auswahl
621
+ * fällt die Einzelauswahl auf das gewählte Label zurück (kein loser Filtertext).
622
+ *
623
+ * Als `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,
624
+ * `formControlName`); der Formularwert ist im Multi-Modus `string[]`, sonst `string`.
625
+ * Ohne Formular gehen `[(value)]` / `[(values)]` (valueChange/valuesChange via model()).
626
+ */
627
+ declare class ComboboxComponent implements ControlValueAccessor {
628
+ private readonly host;
629
+ private readonly input;
630
+ readonly label: _angular_core.InputSignal<string>;
631
+ readonly options: _angular_core.InputSignal<CdsSelectOption[]>;
632
+ /** Einzelauswahl: gewählter Wert. Two-Way (`[(value)]`) UND Angular-Forms. */
633
+ readonly value: _angular_core.ModelSignal<string | undefined>;
634
+ /** Mehrfachauswahl: gewählte Werte (nur bei multi). Two-Way UND Angular-Forms. */
635
+ readonly values: _angular_core.ModelSignal<string[]>;
636
+ readonly multi: _angular_core.InputSignal<boolean>;
637
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
638
+ readonly placeholder: _angular_core.InputSignal<string>;
639
+ readonly emptyText: _angular_core.InputSignal<string>;
640
+ /** Deaktiviert; auch über Angular-Forms (setDisabledState) steuerbar. */
641
+ readonly disabled: _angular_core.ModelSignal<boolean>;
642
+ /** @internal */
643
+ protected readonly open: _angular_core.WritableSignal<boolean>;
644
+ /** @internal */
645
+ protected readonly activeIndex: _angular_core.WritableSignal<number>;
646
+ /**
647
+ * Aktuell gewählte Werte — reiner Ableitungszustand aus `[(value)]`/`[(values)]`,
648
+ * je nach Modus (WP5 §5.3: vorher ein per `effect()` nachgeführtes Signal; die
649
+ * `effect()`-Zustandsableitung ist das Anti-Muster, das die Angular-Doku
650
+ * ausdrücklich nennt). Alle Schreibpfade (`select()`, `removeValue()`,
651
+ * `writeValue()`) schreiben seitdem direkt in `value`/`values` — die Quelle,
652
+ * nicht mehr in dieses abgeleitete Signal.
653
+ *
654
+ * @internal
655
+ */
656
+ protected readonly selected: _angular_core.Signal<string[]>;
657
+ /** Label der aktuellen Einzelauswahl (leer bei Multi/keiner Auswahl). */
658
+ private readonly selectedLabel;
659
+ /**
660
+ * Sichtbarer Filtertext im Feld. Vorgabe: leer im Multi-Modus, sonst das Label
661
+ * der aktuellen Auswahl — lokal überschreibbar (Tippen via `onInput`,
662
+ * `select()`/`clear()`/`close()` setzen ihn ebenfalls direkt). Aktualisiert sich
663
+ * NICHT von der Vorgabe her, während das Menü offen ist (Nutzer tippt gerade);
664
+ * erst das nächste Schließen übernimmt die neue Vorgabe. Ersetzt den Teil des
665
+ * bisherigen `effect()`, der `query` außerhalb des offenen Menüs nachführte
666
+ * (WP5 §5.3).
667
+ *
668
+ * @internal
669
+ */
670
+ protected readonly query: _angular_core.WritableSignal<string>;
671
+ private onChange;
672
+ private onTouched;
673
+ private readonly instance;
674
+ /** @internal */
675
+ protected readonly ids: {
676
+ label: string;
677
+ menu: string;
678
+ option: (i: number) => string;
679
+ };
680
+ /**
681
+ * ControlValueAccessor — Formularwert ist string[] (multi) bzw. string (single).
682
+ *
683
+ * @internal
684
+ */
685
+ writeValue(value: string | string[] | null): void;
686
+ /** @internal */
687
+ registerOnChange(fn: (value: string | string[]) => void): void;
688
+ /** @internal */
689
+ registerOnTouched(fn: () => void): void;
690
+ /** @internal */
691
+ setDisabledState(isDisabled: boolean): void;
692
+ /**
693
+ * Aktuell gewählte Optionen (für die Chips im Multi-Modus).
694
+ *
695
+ * @internal
696
+ */
697
+ protected selectedOptions(): CdsSelectOption[];
698
+ /**
699
+ * Gefilterte Optionen: Substring (case-insensitiv); im Multi-Modus ohne bereits Gewählte.
700
+ *
701
+ * @internal
702
+ */
703
+ protected filtered(): CdsSelectOption[];
704
+ /** @internal */
705
+ protected isSelected(value: string): boolean;
706
+ /** @internal */
707
+ protected focusInput(): void;
708
+ /** @internal */
709
+ protected openMenu(): void;
710
+ /** @internal */
711
+ protected close(): void;
712
+ /** @internal */
713
+ protected onInput(event: Event): void;
714
+ /** @internal */
715
+ protected select(opt: CdsSelectOption): void;
716
+ /** @internal */
717
+ protected removeValue(value: string, event?: Event): void;
718
+ /** @internal */
719
+ protected clear(event?: Event): void;
720
+ /** @internal */
721
+ protected markTouched(): void;
722
+ /** @internal */
723
+ protected onKeydown(event: KeyboardEvent): void;
724
+ private readonly scrollTimer;
725
+ private scrollActive;
726
+ /** @internal */
727
+ protected onDocPointerDown(event: PointerEvent): void;
728
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ComboboxComponent, never>;
729
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ComboboxComponent, "cds-combobox", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "values": { "alias": "values"; "required": false; "isSignal": true; }; "multi": { "alias": "multi"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "values": "valuesChange"; "disabled": "disabledChange"; }, never, never, true, never>;
730
+ }
731
+
732
+ /**
733
+ * Slider — Wrapper um `.field-slider` / `.slider` aus css/components.css → „Slider“.
734
+ *
735
+ * Range-Eingabe mit Label + Live-Ausgabe, bereichsgefärbtem Thumb/Output
736
+ * (.slider-<area> setzt --sl-color), automatisch berechneten Ticks und Helper-Text.
737
+ *
738
+ * Ticks: Es wird nur eine gewünschte ANZAHL (`tickCount`) angegeben; die Positionen/
739
+ * Labels werden gleichmäßig aus [min, max] berechnet (space-between wie das CSS-
740
+ * Layout). Wird der Slider zu schmal, reduziert die Komponente die Tick-Zahl reaktiv
741
+ * (ResizeObserver), sodass die Labels nicht überlappen — Endpunkte bleiben erhalten.
742
+ *
743
+ * Als `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,
744
+ * `formControlName`); ohne Formular geht `[(value)]` (valueChange via model()).
745
+ */
746
+ declare class SliderComponent extends CvaBase<number> {
747
+ private readonly host;
748
+ private readonly destroyRef;
749
+ /** Gemessene Slider-Breite (px); treibt die reaktive Tick-Reduktion. */
750
+ private readonly width;
751
+ readonly label: _angular_core.InputSignal<string>;
752
+ /** Markenbereich → .slider-<area> (Thumb- + Output-Farbe). */
753
+ readonly area: _angular_core.InputSignal<CdsArea>;
754
+ readonly min: _angular_core.InputSignalWithTransform<number, unknown>;
755
+ readonly max: _angular_core.InputSignalWithTransform<number, unknown>;
756
+ readonly step: _angular_core.InputSignalWithTransform<number, unknown>;
757
+ /** Aktueller Wert. Two-Way (`[(value)]`) UND Angular-Forms. */
758
+ readonly value: _angular_core.ModelSignal<number>;
759
+ /** Einheit, an den formatierten Wert angehängt (z. B. ' €'). */
760
+ readonly unit: _angular_core.InputSignal<string>;
761
+ /** Gewünschte Anzahl Ticks (inkl. Endpunkte). 0 = keine. Wird bei zu schmalem
762
+ * Slider automatisch reduziert. */
763
+ readonly tickCount: _angular_core.InputSignalWithTransform<number, unknown>;
764
+ /** Mindestbreite (px) pro Tick-Label, ab der reduziert wird. */
765
+ readonly minTickSpacing: _angular_core.InputSignalWithTransform<number, unknown>;
766
+ readonly helper: _angular_core.InputSignal<string>;
767
+ /** Deaktiviert; auch über Angular-Forms (setDisabledState) steuerbar. */
768
+ readonly disabled: _angular_core.ModelSignal<boolean>;
769
+ readonly sliderId: _angular_core.InputSignal<string>;
770
+ constructor();
771
+ /** @internal */
772
+ protected normalizeValue(value: number): number;
773
+ private clamp;
774
+ /** @internal */
775
+ protected applyValue(value: number): void;
776
+ /** @internal */
777
+ protected applyDisabled(disabled: boolean): void;
778
+ /** @internal */
779
+ protected readonly sliderClasses: _angular_core.Signal<string>;
780
+ /** @internal */
781
+ protected readonly outputClasses: _angular_core.Signal<string>;
782
+ /** @internal */
783
+ protected readonly formatted: _angular_core.Signal<string>;
784
+ /** Effektive Tick-Anzahl: Wunsch, aber auf das reduziert, was in die Breite passt. */
785
+ private effectiveTickCount;
786
+ /**
787
+ * Gleichmäßig über [min, max] verteilte Ticks: Label (kompakt formatiert) plus
788
+ * absolute Ziel-Position (left), zentriert auf die echte Thumb-Position.
789
+ *
790
+ * @internal
791
+ */
792
+ protected readonly tickItems: _angular_core.Signal<{
793
+ label: string;
794
+ left: string;
795
+ }[]>;
796
+ /** Kompakte Tick-Beschriftung: k/M-Kurzform (de-DE), z. B. 32500 → „32,5k“. */
797
+ private formatTick;
798
+ /** @internal */
799
+ protected onInput(event: Event): void;
800
+ /** @internal */
801
+ protected markTouched(): void;
802
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SliderComponent, never>;
803
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SliderComponent, "cds-slider", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "unit": { "alias": "unit"; "required": false; "isSignal": true; }; "tickCount": { "alias": "tickCount"; "required": false; "isSignal": true; }; "minTickSpacing": { "alias": "minTickSpacing"; "required": false; "isSignal": true; }; "helper": { "alias": "helper"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "sliderId": { "alias": "sliderId"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "disabled": "disabledChange"; }, never, never, true, never>;
804
+ }
805
+
806
+ interface CdsFooterLink {
807
+ label: string;
808
+ href: string;
809
+ }
810
+ /** Built-in-Plattformen mit verifiziertem Icon. Weitere über `iconPath` möglich. */
811
+ type CdsSocialPlatform = 'linkedin' | 'youtube';
812
+ interface CdsSocialLink {
813
+ href: string;
814
+ /** Built-in-Plattform (bringt Icon + Label mit). */
815
+ platform?: CdsSocialPlatform;
816
+ /** Aria-Label; Default: das Label der Plattform. */
817
+ label?: string;
818
+ /** Eigenes SVG-Pfad-`d` (viewBox 0 0 24, weiß) — für Plattformen ohne Built-in. */
819
+ iconPath?: string;
820
+ }
821
+ /**
822
+ * Footer — unterer Teil (`.footer-btm`): dunkler Streifen mit Copyright, Rechts-Links
823
+ * und Social-Profilen. Die Host-Klasse `footer-btm` trägt Hintergrund/Flex-Layout aus
824
+ * css/components.css. Social-Glyphen sind schlanke Inline-SVGs in Weiß; verifizierte
825
+ * Built-in-Icons (linkedin, youtube) via `platform`, beliebige weitere via `iconPath`.
826
+ */
827
+ declare class FooterBottomComponent {
828
+ readonly copyright: _angular_core.InputSignal<string>;
829
+ /** Optionale Versionsangabe (z. B. „Version 1.4.2“), hinter dem Copyright. */
830
+ readonly version: _angular_core.InputSignal<string | undefined>;
831
+ /** Optionaler Support-/Hilfe-Link neben den Rechts-Links. */
832
+ readonly support: _angular_core.InputSignal<CdsFooterLink | undefined>;
833
+ readonly legalLinks: _angular_core.InputSignal<CdsFooterLink[]>;
834
+ readonly socialLinks: _angular_core.InputSignal<CdsSocialLink[]>;
835
+ /** Verifizierte Built-in-Social-Icons (viewBox 0 0 24, weiß). */
836
+ private readonly socialIcons;
837
+ /** @internal */
838
+ protected socialPath(s: CdsSocialLink): string;
839
+ /** @internal */
840
+ protected socialLabel(s: CdsSocialLink): string;
841
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FooterBottomComponent, never>;
842
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FooterBottomComponent, "cds-footer-bottom", never, { "copyright": { "alias": "copyright"; "required": false; "isSignal": true; }; "version": { "alias": "version"; "required": false; "isSignal": true; }; "support": { "alias": "support"; "required": false; "isSignal": true; }; "legalLinks": { "alias": "legalLinks"; "required": false; "isSignal": true; }; "socialLinks": { "alias": "socialLinks"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
843
+ }
844
+
845
+ /**
846
+ * Footer — `<footer>`-Landmark (`.footer`, Zwei-Band-Stack) als schlanke Hülle. Die
847
+ * beiden Bänder werden als `<cds-footer-main>` und `<cds-footer-bottom>` projiziert:
848
+ *
849
+ * ```html
850
+ * <cds-footer>
851
+ * <cds-footer-main ...></cds-footer-main>
852
+ * <cds-footer-bottom ...></cds-footer-bottom>
853
+ * </cds-footer>
854
+ * ```
855
+ *
856
+ * So lassen sich oberer und unterer Teil einzeln betrachten und unabhängig
857
+ * konfigurieren; `.footer` stapelt sie (flex column) im Seitenfuß-Landmark.
858
+ */
859
+ declare class FooterComponent {
860
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FooterComponent, never>;
861
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FooterComponent, "cds-footer", never, {}, {}, never, ["*"], true, never>;
862
+ }
863
+
864
+ /**
865
+ * Footer — oberer Teil (`.footer-main`): helles Band als **generisches Spalten-Layout**.
866
+ * Der Inhalt wird als beliebige Spalten projiziert (jedes Top-Level-Kind = eine
867
+ * Grid-Spalte), statt fester Adresse/Nav/Newsletter-Struktur — so eignet es sich für
868
+ * Website- UND App-Footer ohne Marketing-Lock-in.
869
+ *
870
+ * ```html
871
+ * <cds-footer-main>
872
+ * <div>…Spalte 1…</div>
873
+ * <div>…Spalte 2…</div>
874
+ * </cds-footer-main>
875
+ * ```
876
+ *
877
+ * Die Host-Klasse `footer-main` trägt Hintergrund/Padding aus css/components.css;
878
+ * `:host{display:block}` macht das Band auch standalone zum Block. Spaltenanzahl/-breiten
879
+ * über `columns` (grid-template-columns); ohne Angabe gilt das 3-Spalten-Default.
880
+ */
881
+ declare class FooterMainComponent {
882
+ /**
883
+ * Optionale `grid-template-columns` (z. B. `'repeat(4, 1fr)'` oder `'2fr 1fr'`).
884
+ * Ohne Angabe gilt das Default aus `.footer-grid` (1.2fr 1fr 1.3fr, 3 Spalten).
885
+ */
886
+ readonly columns: _angular_core.InputSignal<string | undefined>;
887
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FooterMainComponent, never>;
888
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FooterMainComponent, "cds-footer-main", never, { "columns": { "alias": "columns"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
889
+ }
890
+
891
+ /**
892
+ * Einzelner Tab für `<cds-area-tabs>`. Trägt Label + Bereich; sein Inhalt ist
893
+ * BELIEBIGES projiziertes Markup (Text, Listen, Komponenten, CTAs …), das die
894
+ * Elternkomponente ins zugehörige Panel rendert.
895
+ *
896
+ * Der Inhalt wird in ein internes `<ng-template>` projiziert (via `<ng-content>`)
897
+ * und über einen TemplateRef bereitgestellt — so kann `cds-area-tabs` ihn getrennt
898
+ * vom Tab-Button an der Panel-Position ausgeben (ngTemplateOutlet), passend zur
899
+ * `.area-tabs` / `.atab-content`-Struktur aus css/components.css.
900
+ */
901
+ declare class AreaTabComponent {
902
+ /** Markenbereich → Tab-Punkt (Bereichs-500) + aktiver Text/Unterstrich. */
903
+ readonly area: _angular_core.InputSignal<CdsArea>;
904
+ /** Beschriftung im Tab-Button. */
905
+ readonly label: _angular_core.InputSignal<string>;
906
+ /**
907
+ * Projizierter Panel-Inhalt; von der Elternkomponente via Outlet gerendert.
908
+ *
909
+ * Bleibt `public`, weil `cds-area-tabs` ihn von außen liest — anders als die
910
+ * internen Signale, die ADR-0007 auf `protected` stellt. `@internal` hält ihn
911
+ * trotzdem aus Props-Tabelle und Manifest heraus: Input/Output ist er nicht.
912
+ *
913
+ * @internal
914
+ */
915
+ readonly content: _angular_core.Signal<TemplateRef<unknown>>;
916
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AreaTabComponent, never>;
917
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AreaTabComponent, "cds-area-tab", never, { "area": { "alias": "area"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
918
+ }
919
+
920
+ /**
921
+ * AreaTabs — Wrapper um `.area-tabs` / `.atab` / `.atab-content` aus
922
+ * css/components.css → „Area Tabs“. Bereichsgefärbte Tab-Leiste: der aktive Tab
923
+ * setzt `--atab-color` (Bereichs-700) für Text + Unterstrich, der Punkt nutzt
924
+ * Bereichs-500. Umschalten per Klick (aria-selected / sichtbares Panel).
925
+ *
926
+ * Tabs werden deklarativ als `<cds-area-tab>`-Kinder projiziert; jeder Tab trägt
927
+ * `area` + `label` und BELIEBIGEN Inhalt (Markup/Komponenten), der ins Panel
928
+ * gerendert wird. Der aktive Index ist über `[(active)]` steuerbar.
929
+ */
930
+ declare class AreaTabsComponent {
931
+ private readonly host;
932
+ private readonly instance;
933
+ /**
934
+ * Die Tabs kommen als projizierte `<cds-area-tab>`-Kinder.
935
+ *
936
+ * @internal
937
+ */
938
+ protected readonly tabs: _angular_core.Signal<readonly AreaTabComponent[]>;
939
+ /** Index des aktiven Tabs. Two-Way (`[(active)]`). */
940
+ readonly active: _angular_core.ModelSignal<number>;
941
+ /** Zugänglicher Name der Tab-Leiste (WAI-ARIA verlangt aria-label/-labelledby). */
942
+ readonly ariaLabel: _angular_core.InputSignal<string>;
943
+ /**
944
+ * Aktiv-Akzent je Bereich: ki braucht -800 (700 reißt AA), sonst -700 (wie .t-*).
945
+ *
946
+ * @internal
947
+ */
948
+ protected atabAccent(area: CdsArea): string;
949
+ /** @internal */
950
+ protected tabId(i: number): string;
951
+ /** @internal */
952
+ protected panelId(i: number): string;
953
+ /**
954
+ * WAI-ARIA-Tabs-Tastatur (horizontal, automatische Aktivierung): ←/→ bewegen mit
955
+ * Umlauf, Home/End springen an die Enden. Der Fokus wird mitgeführt (Roving
956
+ * Tabindex: nur der aktive Tab ist per Tab erreichbar). Panels laden sofort, daher
957
+ * ist Auswahl = Fokus (APG-empfohlen).
958
+ *
959
+ * @internal
960
+ */
961
+ protected onKeydown(event: KeyboardEvent): void;
962
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AreaTabsComponent, never>;
963
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AreaTabsComponent, "cds-area-tabs", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "active": "activeChange"; }, ["tabs"], never, true, never>;
964
+ }
965
+
966
+ /** Ein Logo: in der Regel ein Bild; der Text dient als Alt-Fallback und als Platzhalter. */
967
+ interface CdsLogo {
968
+ /** Firmen-/Markenname. Pflicht – dient als Alt-Text-Fallback UND als Text-Platzhalter,
969
+ * falls (noch) kein Bild vorliegt. */
970
+ label: string;
971
+ /** Bildquelle (URL oder Data-URI). Gesetzt → Bild wird gezeigt, sonst der Text-Platzhalter. */
972
+ src?: string;
973
+ /** Alt-Text des Bilds (Fallback: `label`). */
974
+ alt?: string;
975
+ }
976
+ /**
977
+ * Logo — einzelne Logo-Kachel (`.logo-tile` aus css/components.css).
978
+ *
979
+ * Rendert bevorzugt ein **Bild** (`src`); ohne Bild fällt es auf den Text-`label`
980
+ * als Platzhalter zurück (`.logo-placeholder`). So lässt es sich sowohl im
981
+ * Logo-Carousel als auch eigenständig verwenden (Partner-Leiste, „Bekannt aus“-Reihe,
982
+ * Footer). Die Host-Klasse `logo-tile` trägt Flex-Zentrierung/Padding aus der portablen CSS.
983
+ */
984
+ declare class LogoComponent {
985
+ readonly label: _angular_core.InputSignal<string>;
986
+ /** Bildquelle; gesetzt → Bild statt Text-Platzhalter. */
987
+ readonly src: _angular_core.InputSignal<string | undefined>;
988
+ /** Alt-Text des Bilds (Fallback: `label`). */
989
+ readonly alt: _angular_core.InputSignal<string>;
990
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LogoComponent, never>;
991
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LogoComponent, "cds-logo", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "src": { "alias": "src"; "required": false; "isSignal": true; }; "alt": { "alias": "alt"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
992
+ }
993
+
994
+ /**
995
+ * LogoCarousel — Wrapper um `.logo-carousel` aus css/components.css → „Logo-Carousel“.
996
+ *
997
+ * Diskrete Sets von je fünf Logos, die automatisch per Crossfade wechseln
998
+ * (`[aria-hidden]` je Slide). Das Autoplay pausiert bei Maus-Hover und Tastatur-Fokus
999
+ * (damit Nutzer in Ruhe lesen/bedienen können), zusätzlich dauerhaft über den
1000
+ * Pause-Button (.logo-carousel-pause, sichtbar bei Hover/Fokus bzw. im .paused-Zustand);
1001
+ * Dots wählen ein Set direkt. Autoplay respektiert prefers-reduced-motion.
1002
+ *
1003
+ * Der Timer wird zentral über ein `effect` gesteuert: er läuft nur, wenn NICHT
1004
+ * pausiert, NICHT gehovert, NICHT fokussiert und reduzierte Bewegung nicht gewünscht
1005
+ * ist. Eine Änderung des `interval` startet ihn automatisch neu.
1006
+ *
1007
+ * Jede Kachel ist ein `cds-logo`: bevorzugt ein Bild (`src`), sonst der Text als
1008
+ * Platzhalter/Fallback. Standardmäßig sind reine Text-Platzhalter gesetzt – reale
1009
+ * Anwendungen übergeben ihre Kundenlogos als Bilder.
1010
+ */
1011
+ declare class LogoCarouselComponent {
1012
+ private readonly host;
1013
+ /** Logo-Sets, die im Wechsel angezeigt werden (mind. ein Eintrag je Set). */
1014
+ readonly sets: _angular_core.InputSignal<CdsLogo[][]>;
1015
+ /** Autoplay-Intervall in **Millisekunden** (Standard 6000 = 6 s). */
1016
+ readonly interval: _angular_core.InputSignal<number>;
1017
+ /** Aktives Set. Two-Way (`[(active)]`) via model(). */
1018
+ readonly active: _angular_core.ModelSignal<number>;
1019
+ /**
1020
+ * Vom Nutzer explizit pausiert (Pause-Button).
1021
+ *
1022
+ * @internal
1023
+ */
1024
+ protected readonly paused: _angular_core.WritableSignal<boolean>;
1025
+ /**
1026
+ * Transiente Pause: Maus über dem Carousel.
1027
+ *
1028
+ * @internal
1029
+ */
1030
+ protected readonly hovered: _angular_core.WritableSignal<boolean>;
1031
+ /**
1032
+ * Transiente Pause: Tastatur-Fokus innerhalb des Carousels.
1033
+ *
1034
+ * @internal
1035
+ */
1036
+ protected readonly focused: _angular_core.WritableSignal<boolean>;
1037
+ /** Reduzierte Bewegung gewünscht → kein Autoplay. Einmal beim Erzeugen ermittelt. */
1038
+ private readonly reducedMotion;
1039
+ private readonly uid;
1040
+ constructor();
1041
+ /**
1042
+ * Stabile Slide-id für die aria-controls-Verknüpfung der Dots.
1043
+ *
1044
+ * @internal
1045
+ */
1046
+ protected slideId(i: number): string;
1047
+ /** @internal */
1048
+ protected togglePause(): void;
1049
+ /** @internal */
1050
+ protected goTo(i: number): void;
1051
+ /**
1052
+ * WAI-ARIA-Tabs-Tastatur auf der Dot-Leiste (horizontal, automatische Aktivierung):
1053
+ * ←/→ mit Umlauf, Home/End an die Enden; der Fokus wird mitgeführt (Roving Tabindex).
1054
+ * 1:1 übernommen von `carousel.component.ts` (Indexberechnung in
1055
+ * `../shared/dots-keyboard.ts`, identisch für beide Komponenten).
1056
+ *
1057
+ * @internal
1058
+ */
1059
+ protected onDotsKeydown(event: KeyboardEvent): void;
1060
+ /**
1061
+ * Fokus-Pause nur aufheben, wenn der Fokus das Carousel ganz verlässt (nicht bei
1062
+ * Wechsel zwischen Kind-Elementen).
1063
+ *
1064
+ * @internal
1065
+ */
1066
+ protected onFocusOut(event: FocusEvent): void;
1067
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LogoCarouselComponent, never>;
1068
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LogoCarouselComponent, "cds-logo-carousel", never, { "sets": { "alias": "sets"; "required": true; "isSignal": true; }; "interval": { "alias": "interval"; "required": false; "isSignal": true; }; "active": { "alias": "active"; "required": false; "isSignal": true; }; }, { "active": "activeChange"; }, never, never, true, never>;
1069
+ }
1070
+
1071
+ interface CdsSlide {
1072
+ image?: string;
1073
+ title: string;
1074
+ text: string;
1075
+ }
1076
+ /**
1077
+ * Carousel — Wrapper um `.img-slider` aus css/components.css → „Bild-Slider“.
1078
+ *
1079
+ * Crossfade-Carousel: alle Slides liegen gestapelt im Grid, die aktive trägt
1080
+ * `.active` (opacity). Inaktive Slides bekommen zusätzlich `[aria-hidden]`, sonst
1081
+ * läse ein Screenreader Titel und Text jeder Folie vor, obwohl visuell nur eine
1082
+ * sichtbar ist (identisches Muster wie beim LogoCarousel). Prev/Next-Buttons
1083
+ * (.img-slider-btn) und Dots (.img-dot) steuern den Index. Optionale Hero-Variante
1084
+ * (.img-slider-hero). Ohne Bild-URL wird ein neutraler Platzhalter gezeigt. Der
1085
+ * aktive Index ist über `[(active)]` (model) beobacht-/steuerbar.
1086
+ */
1087
+ declare class CarouselComponent {
1088
+ private readonly host;
1089
+ private readonly instance;
1090
+ /** Anzuzeigende Slides (Bild optional, Titel/Text je Slide Pflicht). */
1091
+ readonly slides: _angular_core.InputSignal<CdsSlide[]>;
1092
+ /** Aktiver Slide-Index. Two-Way (`[(active)]`) via model(). */
1093
+ readonly active: _angular_core.ModelSignal<number>;
1094
+ /** Hero-Variante (vollflächig, 21:9, Caption als Overlay) → .img-slider-hero. */
1095
+ readonly hero: _angular_core.InputSignal<boolean>;
1096
+ /** @internal */
1097
+ protected readonly wrapClasses: _angular_core.Signal<"img-slider img-slider-hero" | "img-slider">;
1098
+ /** @internal */
1099
+ protected prev(): void;
1100
+ /** @internal */
1101
+ protected next(): void;
1102
+ /** @internal */
1103
+ protected slideId(i: number): string;
1104
+ /**
1105
+ * WAI-ARIA-Tabs-Tastatur auf der Dot-Leiste (horizontal, automatische Aktivierung):
1106
+ * ←/→ mit Umlauf, Home/End an die Enden; der Fokus wird mitgeführt (Roving Tabindex).
1107
+ * Indexberechnung in `../shared/dots-keyboard.ts` (identisch mit LogoCarousel).
1108
+ *
1109
+ * @internal
1110
+ */
1111
+ protected onDotsKeydown(event: KeyboardEvent): void;
1112
+ /** @internal */
1113
+ protected readonly placeholder = "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='800'%20height='450'%3E%3Crect%20width='800'%20height='450'%20fill='%23E8EDED'/%3E%3Ctext%20x='400'%20y='225'%20font-family='sans-serif'%20font-size='24'%20fill='%236E8585'%20text-anchor='middle'%20dominant-baseline='middle'%3EBild%3C/text%3E%3C/svg%3E";
1114
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CarouselComponent, never>;
1115
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CarouselComponent, "cds-carousel", never, { "slides": { "alias": "slides"; "required": true; "isSignal": true; }; "active": { "alias": "active"; "required": false; "isSignal": true; }; "hero": { "alias": "hero"; "required": false; "isSignal": true; }; }, { "active": "activeChange"; }, never, never, true, never>;
1116
+ }
1117
+
1118
+ /**
1119
+ * Theme-Segment — Segment-Switch für das Farbthema. Vorgesehener Einsatz: als
1120
+ * eigenständiges Element zum Hovern. Ist daher IMMER responsiv (unter 640px
1121
+ * Icon-only) und IMMER animiert (Aktiv-Markierung gleitet als Thumb) — beides
1122
+ * fest, nicht konfigurierbar. Icon + Textlabel stehen immer nebeneinander.
1123
+ *
1124
+ * Einzige Konfiguration: `showSystem` (tri Hell/Dunkel/System vs. binär Hell/Dunkel).
1125
+ *
1126
+ * Baut auf den CSS-Kern-Klassen `.theme-bar`/`.tbtn` auf. Jeder Button trägt ein
1127
+ * `aria-label`, ist also auch im Icon-only-Modus benannt. Der Thumb wird per
1128
+ * getBoundingClientRect an die aktive Zelle gesetzt (ResizeObserver misst bei
1129
+ * Breakpoint-/Font-Änderungen nach).
1130
+ */
1131
+ declare class ThemeSegmentComponent {
1132
+ /** true → Hell/Dunkel/System (tri), false → nur Hell/Dunkel (binär). */
1133
+ readonly showSystem: _angular_core.InputSignal<boolean>;
1134
+ /** @internal */
1135
+ protected readonly svc: ThemeModeService;
1136
+ /** @internal */
1137
+ protected readonly icon: Record<_conciso_design_system_angular.CdsThemeMode, string>;
1138
+ /** @internal */
1139
+ protected readonly label: Record<_conciso_design_system_angular.CdsThemeMode, string>;
1140
+ /** @internal */
1141
+ protected readonly order: _angular_core.Signal<_conciso_design_system_angular.CdsThemeMode[]>;
1142
+ private readonly bar;
1143
+ private readonly thumb;
1144
+ private readonly opts;
1145
+ private readonly destroyRef;
1146
+ constructor();
1147
+ /** Thumb-Geometrie relativ zur Leiste messen (reines Lesen, keine Schreibzugriffe). */
1148
+ private measureThumb;
1149
+ /** Gemessene Geometrie auf den Thumb schreiben (reines Schreiben, kein Lesen). */
1150
+ private applyThumb;
1151
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeSegmentComponent, never>;
1152
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ThemeSegmentComponent, "cds-theme-segment", never, { "showSystem": { "alias": "showSystem"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1153
+ }
1154
+
1155
+ /**
1156
+ * Theme-Dropdown — Theme-Umschalter auf Basis unseres Custom Select (cds-select):
1157
+ * gestylte Einzelauswahl mit Listbox-Popup und Häkchen. Vorgesehener Einsatz: nur in
1158
+ * den Einstellungen (Settings), NICHT als persistentes Element auf allen Seiten.
1159
+ *
1160
+ * `showSystem` schaltet zwischen Hell/Dunkel/System und binär Hell/Dunkel.
1161
+ */
1162
+ declare class ThemeSelectComponent {
1163
+ /** true → Hell/Dunkel/System, false → nur Hell/Dunkel. */
1164
+ readonly showSystem: _angular_core.InputSignal<boolean>;
1165
+ /** @internal */
1166
+ protected readonly svc: ThemeModeService;
1167
+ /** @internal */
1168
+ protected readonly options: _angular_core.Signal<CdsSelectOption[]>;
1169
+ /** @internal */
1170
+ protected onChange(value: string | undefined): void;
1171
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeSelectComponent, never>;
1172
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ThemeSelectComponent, "cds-theme-select", never, { "showSystem": { "alias": "showSystem"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1173
+ }
1174
+
1175
+ /**
1176
+ * Card — Wrapper um `.card` aus css/components.css → „Cards“.
1177
+ *
1178
+ * Die Karte rendert `<article class="card">` und ruht damit flach mit Rahmen. Das folgt der
1179
+ * Konvention „Elevation = Interaktivität“: Schatten trägt eine Karte nur, wenn die Karte selbst
1180
+ * der klickbare Bereich ist. Hier liegt die Interaktion in der Footer-Aktion, nicht in der Fläche.
1181
+ * `.card-elevated` wirkt im CSS ausschließlich auf `a.card-elevated`; eine Link-Karten-Variante
1182
+ * (`<a>` mit Ziel statt `<article>` mit Button) ist deshalb eine eigene Komponente/Variante.
1183
+ *
1184
+ * Bildet die im CSS vorgesehene Struktur ab: .card-media (bereichsgefärbt via
1185
+ * [data-area]) mit der echten Bereichs-Glyphe, .card-body mit .card-eyebrow /
1186
+ * .card-title / .card-text und ein optionales .card-footer mit einer Text-Aktion.
1187
+ *
1188
+ * Alle Textteile sind optional (leer = ausgeblendet); zusätzlich nimmt `.card-body`
1189
+ * beliebigen projizierten Inhalt via `<ng-content>` auf — so eignet sich die Karte
1190
+ * auch für freie Listen-/Detail-Inhalte in SPAs, nicht nur die Marketing-Struktur.
1191
+ * Die Footer-Aktion meldet Klicks über `actionClick`.
1192
+ */
1193
+ declare class CardComponent {
1194
+ private readonly sanitizer;
1195
+ /** Kicker-Text oberhalb des Titels (leer = keine Eyebrow-Zeile). */
1196
+ readonly eyebrow: _angular_core.InputSignal<string>;
1197
+ /** Kartentitel. */
1198
+ readonly title: _angular_core.InputSignal<string>;
1199
+ /** Anreißer-/Beschreibungstext der Karte. */
1200
+ readonly text: _angular_core.InputSignal<string>;
1201
+ /** Markenbereich → data-area (färbt Media-Glyphe + Eyebrow). */
1202
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
1203
+ /** Bereichsgefärbte Medienfläche mit Bereichs-Glyphe anzeigen. */
1204
+ readonly showMedia: _angular_core.InputSignal<boolean>;
1205
+ /** Kompakte Text-Aktion im Footer (leer = kein Footer). */
1206
+ readonly actionLabel: _angular_core.InputSignal<string>;
1207
+ /** Klick auf die Footer-Aktion. */
1208
+ readonly actionClick: _angular_core.OutputEmitterRef<void>;
1209
+ /** @internal */
1210
+ protected readonly actionClasses: _angular_core.Signal<string>;
1211
+ /**
1212
+ * Echte Bereichs-Glyphe aus icons/icons.js, als ico-48-SVG in die Media-Fläche.
1213
+ *
1214
+ * @internal
1215
+ */
1216
+ protected readonly mediaSvg: _angular_core.Signal<SafeHtml>;
1217
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CardComponent, never>;
1218
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CardComponent, "cds-card", never, { "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "text": { "alias": "text"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "showMedia": { "alias": "showMedia"; "required": false; "isSignal": true; }; "actionLabel": { "alias": "actionLabel"; "required": false; "isSignal": true; }; }, { "actionClick": "actionClick"; }, never, ["*"], true, never>;
1219
+ }
1220
+
1221
+ /**
1222
+ * StatCard — Wrapper um `.card-stat` aus css/components.css → „Stat Card“.
1223
+ *
1224
+ * Flache, statische Kennzahlen-Karte mit bereichsgefärbtem Top-Akzent (data-area),
1225
+ * großem Wert (.card-stat-value), Label (.card-stat-label) und optionalem
1226
+ * Trend-Pill (.card-stat-trend.up/.down) inkl. Richtungs-Pfeil — wie docs/index.html.
1227
+ */
1228
+ declare class StatCardComponent {
1229
+ /** Anzeigewert der Kennzahl. */
1230
+ readonly value: _angular_core.InputSignal<string>;
1231
+ /** Beschriftung der Kennzahl. */
1232
+ readonly label: _angular_core.InputSignal<string>;
1233
+ /** Markenbereich → data-area (Top-Akzent + Wertfarbe). */
1234
+ readonly area: _angular_core.InputSignal<CdsArea>;
1235
+ /** Trendrichtung → .card-stat-trend.up / .down (leer = kein Pill). */
1236
+ readonly trend: _angular_core.InputSignal<"up" | "down" | undefined>;
1237
+ /** Text neben dem Trend-Pfeil (nur sichtbar, wenn `trend` gesetzt ist). */
1238
+ readonly trendText: _angular_core.InputSignal<string>;
1239
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatCardComponent, never>;
1240
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatCardComponent, "cds-stat-card", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "trend": { "alias": "trend"; "required": false; "isSignal": true; }; "trendText": { "alias": "trendText"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1241
+ }
1242
+
1243
+ /** Eine Kennzahl im Stat-Strip. */
1244
+ interface CdsFlatStat {
1245
+ area?: CdsArea;
1246
+ value: string;
1247
+ label: string;
1248
+ }
1249
+ /**
1250
+ * StatStrip — Wrapper um `.card-stat-strip` + `.card-stat-flat` aus
1251
+ * css/components.css → „Stat-Strip“. Flacher Bandstreifen (auto-fit-Grid auf
1252
+ * --n-50-Grund) mit zentrierten Kennzahlen ohne Rahmen/Schatten; Wert je
1253
+ * Bereich getönt via [data-area]. Genau wie docs/index.html.
1254
+ */
1255
+ declare class StatStripComponent {
1256
+ /** Kennzahlen des Streifens. */
1257
+ readonly stats: _angular_core.InputSignal<CdsFlatStat[]>;
1258
+ /** Abgerundete Ecken (--r-lg) wie in der Doku-Verwendung. */
1259
+ readonly rounded: _angular_core.InputSignal<boolean>;
1260
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatStripComponent, never>;
1261
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatStripComponent, "cds-stat-strip", never, { "stats": { "alias": "stats"; "required": true; "isSignal": true; }; "rounded": { "alias": "rounded"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1262
+ }
1263
+
1264
+ /**
1265
+ * Blockquote — Wrapper um `.bq` aus css/components.css → „Blockquote“.
1266
+ *
1267
+ * Bereichsgefärbtes Zitat mit linker Akzentleiste und getöntem Grund (data-area),
1268
+ * Quote-Icon (ui-quote, dieselbe Glyphe wie docs/index.html), Zitat und
1269
+ * Caption (Name/Rolle). Nur bestehende Klassen.
1270
+ *
1271
+ * **Nicht `cds-article-pullquote` (`.article-pullquote`).** Dieses Bauteil ist
1272
+ * ein eigenständiges Zitat: eine dritte, benannte Person (`name`/`roleLabel` sind
1273
+ * Pflicht), mit getönter Akzent-Box und Quote-Icon. `cds-article-pullquote` ist
1274
+ * dagegen ein typografischer Akzent im eigenen Lauftext eines Wissensbeitrags,
1275
+ * ohne Attribution, ohne Box, ohne Icon — der Autor zitiert dort einen Satz aus
1276
+ * dem eigenen Text, nicht eine dritte Stimme. Volle Abgrenzung samt Tabelle in
1277
+ * dessen Klassendoku (`article-pullquote.component.ts`).
1278
+ */
1279
+ declare class BlockquoteComponent {
1280
+ private readonly sanitizer;
1281
+ /** Zitattext. */
1282
+ readonly quote: _angular_core.InputSignal<string>;
1283
+ /** Name der zitierten Person. */
1284
+ readonly name: _angular_core.InputSignal<string>;
1285
+ /** Rolle/Funktion der zitierten Person (leer = keine Caption-Zeile dafür). */
1286
+ readonly roleLabel: _angular_core.InputSignal<string>;
1287
+ /** Markenbereich → data-area (Akzentleiste + getönter Grund). */
1288
+ readonly area: _angular_core.InputSignal<CdsArea>;
1289
+ /**
1290
+ * Zitat-Icon aus der zentralen Icon-Registry (icons.ts) statt dreifach
1291
+ * dupliziertem SVG-Pfad in Blockquote/Testimonial/TeamVoice.
1292
+ *
1293
+ * @internal
1294
+ */
1295
+ protected readonly quoteIcon: _angular_core.Signal<SafeHtml>;
1296
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BlockquoteComponent, never>;
1297
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BlockquoteComponent, "cds-blockquote", never, { "quote": { "alias": "quote"; "required": true; "isSignal": true; }; "name": { "alias": "name"; "required": true; "isSignal": true; }; "roleLabel": { "alias": "roleLabel"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1298
+ }
1299
+
1300
+ /**
1301
+ * CodeBlock — Wrapper um `.cb-wrap` aus css/components.css → „Code-Block“.
1302
+ *
1303
+ * Header mit Sprach-Label (.cb-lang) und optionalem Kopier-Button (.cb-copy),
1304
+ * darunter der Code in `pre.cb-body` (white-space:pre, horizontal scrollbar).
1305
+ * Optionale Terminal-Variante (.cb-terminal). Syntax-Highlighting-Spans
1306
+ * (.k/.v/.s/…) werden hier bewusst nicht gesetzt — der Code bleibt Klartext.
1307
+ *
1308
+ * A11y (siehe docs/komponenten/code-block-verwendung.mdx, Abschnitt „Barrierefreiheit“):
1309
+ * - `<code>` im `<pre>` als semantisches Grundgerüst, damit Screenreader den Inhalt
1310
+ * als „Code“ ankündigen. `.cb-body code{font:inherit}` in components.css fängt den
1311
+ * Browser-Default (`code{font-family:monospace}`) ab, sonst würde das verschachtelte
1312
+ * `<code>` eine andere Schrift als der Rest des Blocks zeigen.
1313
+ * - `tabindex="0"` auf `pre.cb-body`, weil der Block bei langen Zeilen horizontal
1314
+ * scrollt und sonst per Tastatur nicht erreichbar wäre.
1315
+ * - `aria-label="Code kopieren"` auf dem Kopier-Button ist **stabil** und wechselt nach
1316
+ * dem Klick nicht mehr. Ein Bedienelement trägt den Namen seiner Funktion, nicht den
1317
+ * seines letzten Ereignisses — sonst findet man den Button per Sprachsteuerung danach
1318
+ * nicht mehr, und eine Elementliste zeigt einen Button „Code kopiert“, der tatsächlich
1319
+ * kopiert. Die Erfolgsmeldung läuft stattdessen über eine eigene, visuell versteckte
1320
+ * Live-Region (`.sr-only` + `role="status"`, Muster aus `snackbar.component.ts`), die
1321
+ * von Anfang an im DOM steht und nur ihren Textinhalt wechselt: `aria-live` beobachtet
1322
+ * Inhalts-, keine Attribut-Änderungen, und eine Region, die erst beim Klick entsteht,
1323
+ * kündigt bei vielen Screenreadern nichts an. Zusätzlich verhalten sich Live-Regionen
1324
+ * auf dem gerade fokussierten Element (hier: der Button nach dem Klick) uneinheitlich.
1325
+ * Der sichtbare Button-Text wechselt weiterhin „Kopieren“ ↔ „Kopiert!“, ist aber durch
1326
+ * `aria-label` für die Namensberechnung überschrieben und rein optisches Feedback.
1327
+ */
1328
+ declare class CodeBlockComponent {
1329
+ /** Sprach-Label im Header (.cb-lang), rein informativ, ohne Syntax-Highlighting. */
1330
+ readonly lang: _angular_core.InputSignal<string>;
1331
+ /** Anzuzeigender Code (Klartext, `pre`-formatiert). */
1332
+ readonly code: _angular_core.InputSignal<string>;
1333
+ /** Terminal-Optik → .cb-terminal. */
1334
+ readonly terminal: _angular_core.InputSignal<boolean>;
1335
+ /** Kopier-Button anzeigen (.cb-copy). */
1336
+ readonly copyable: _angular_core.InputSignal<boolean>;
1337
+ /** @internal */
1338
+ protected readonly copied: _angular_core.WritableSignal<boolean>;
1339
+ private readonly destroyRef;
1340
+ /** Reset-Timer des „Kopiert!“-Feedbacks; gemerkt, um ihn zu clearen. */
1341
+ private resetTimer?;
1342
+ constructor();
1343
+ /** @internal */
1344
+ protected readonly wrapClasses: _angular_core.Signal<"cb-wrap cb-terminal" | "cb-wrap">;
1345
+ /**
1346
+ * Text der Live-Region (`role="status"`) neben dem Button. Leer im Ruhezustand, damit
1347
+ * ein erneuter Klick nach Ablauf des Reset-Timers wieder von „“ auf „Code kopiert.“
1348
+ * wechselt und so erneut als Änderung erkannt und angekündigt wird.
1349
+ *
1350
+ * @internal
1351
+ */
1352
+ protected readonly copyStatus: _angular_core.Signal<"" | "Code kopiert.">;
1353
+ /** @internal */
1354
+ protected copy(): void;
1355
+ private clearResetTimer;
1356
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CodeBlockComponent, never>;
1357
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CodeBlockComponent, "cds-code-block", never, { "lang": { "alias": "lang"; "required": false; "isSignal": true; }; "code": { "alias": "code"; "required": true; "isSignal": true; }; "terminal": { "alias": "terminal"; "required": false; "isSignal": true; }; "copyable": { "alias": "copyable"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1358
+ }
1359
+
1360
+ /** Ein FAQ-Eintrag. */
1361
+ interface CdsFaqItem {
1362
+ /** Frage (Summary-Zeile). */
1363
+ q: string;
1364
+ /** Antworttext. */
1365
+ a: string;
1366
+ }
1367
+ /**
1368
+ * Faq — Wrapper um `.ep-faq` aus css/components.css → „FAQ-Accordion“.
1369
+ *
1370
+ * Nutzt natives `<details>/<summary>` (kein JS nötig): Auf-/Zuklappen, Tastatur
1371
+ * und Zugänglichkeit kommen vom Browser. Der Caret (.ep-faq-caret) dreht via
1372
+ * `details[open]`. Antwort in `.ep-faq-a`.
1373
+ */
1374
+ declare class FaqComponent {
1375
+ /** Fragen-/Antworten-Liste des Akkordeons. */
1376
+ readonly items: _angular_core.InputSignal<CdsFaqItem[]>;
1377
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FaqComponent, never>;
1378
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FaqComponent, "cds-faq", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1379
+ }
1380
+
1381
+ /**
1382
+ * Skala (cds-scale) — Slider für GEORDNETE (ordinale) Kategorien, deren Labels die
1383
+ * Werte SIND (z. B. Niedrig < Mittel < Hoch, nie < selten < oft < immer).
1384
+ *
1385
+ * Basiert auf dem nativen <input type="range">; min=0, max=labels.length-1, step=1
1386
+ * werden intern abgeleitet und NICHT exponiert. Der aktuelle Wert erscheint als
1387
+ * LABEL im <output> und wird Screenreadern über `aria-valuetext` als Text gemeldet
1388
+ * (nicht als Zahl) — das anerkannte APG-Muster für ordinale Slider. Die Skalenpunkte
1389
+ * zeigen alle Labels, exakt auf ihre Position ausgerichtet und bewusst OHNE
1390
+ * Reduktion (jedes Label ist eine wählbare Stufe).
1391
+ *
1392
+ * NUR für geordnete Kategorien. Ungeordnete/gleichrangige Optionen (ohne natürliche
1393
+ * Reihenfolge) gehören NICHT auf einen Slider → cds-radio-group oder cds-area-tabs.
1394
+ *
1395
+ * Als `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,
1396
+ * `formControlName`); der Formularwert ist der Stufen-INDEX. Ohne Formular geht
1397
+ * `[(value)]` (valueChange via model()).
1398
+ */
1399
+ declare class ScaleComponent extends CvaBase<number> {
1400
+ /** Feld-Label (die Frage), z. B. „Zufriedenheit“. */
1401
+ readonly label: _angular_core.InputSignal<string>;
1402
+ /** Geordnete Skalen-Labels; sie sind zugleich die Werte. */
1403
+ readonly labels: _angular_core.InputSignal<string[]>;
1404
+ /** Gewählte Stufe als Index (0-basiert). Two-Way (`[(value)]`) UND Angular-Forms. */
1405
+ readonly value: _angular_core.ModelSignal<number>;
1406
+ /** Markenbereich → Thumb-/Output-Farbe. */
1407
+ readonly area: _angular_core.InputSignal<CdsArea>;
1408
+ readonly helper: _angular_core.InputSignal<string>;
1409
+ /** Deaktiviert; auch über Angular-Forms (setDisabledState) steuerbar. */
1410
+ readonly disabled: _angular_core.ModelSignal<boolean>;
1411
+ readonly scaleId: _angular_core.InputSignal<string>;
1412
+ constructor();
1413
+ /** @internal */
1414
+ protected normalizeValue(value: number): number;
1415
+ /** @internal */
1416
+ protected applyValue(value: number): void;
1417
+ /** @internal */
1418
+ protected applyDisabled(disabled: boolean): void;
1419
+ /**
1420
+ * Oberer Index (aus der Label-Zahl abgeleitet, nicht exponiert).
1421
+ *
1422
+ * @internal
1423
+ */
1424
+ protected readonly max: _angular_core.Signal<number>;
1425
+ /** @internal */
1426
+ protected readonly currentLabel: _angular_core.Signal<string>;
1427
+ /** @internal */
1428
+ protected readonly sliderClasses: _angular_core.Signal<string>;
1429
+ /** @internal */
1430
+ protected readonly outputClasses: _angular_core.Signal<string>;
1431
+ /**
1432
+ * Alle Labels + Positions-Style. Mitte-Labels sind auf ihrer Thumb-Position
1433
+ * zentriert; das ERSTE/LETZTE Label wird an der jeweiligen Kante verankert
1434
+ * (linksbündig bei 11px bzw. rechtsbündig bei Breite−11px), damit lange
1435
+ * Kategorie-Labels an den Enden nicht über den Rand hinaus abgeschnitten werden.
1436
+ * (11px = halbe Thumb-Breite, siehe css/components.css.)
1437
+ *
1438
+ * @internal
1439
+ */
1440
+ protected readonly tickItems: _angular_core.Signal<{
1441
+ label: string;
1442
+ style: Record<string, string>;
1443
+ }[]>;
1444
+ /** @internal */
1445
+ protected onInput(event: Event): void;
1446
+ /** @internal */
1447
+ protected markTouched(): void;
1448
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ScaleComponent, never>;
1449
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ScaleComponent, "cds-scale", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "helper": { "alias": "helper"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "scaleId": { "alias": "scaleId"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "disabled": "disabledChange"; }, never, never, true, never>;
1450
+ }
1451
+
1452
+ type CdsSnackTone = 'def' | 'ok' | 'err';
1453
+ /**
1454
+ * Snackbar — Wrapper um `.snack` aus css/components.css → „Snackbar“.
1455
+ *
1456
+ * Kurze Statusmeldung in drei Tönen (.snack-def / .snack-ok / .snack-err) mit
1457
+ * führendem, tonfarbenem Icon (wie die Doku) und optionaler Aktion (.snack-act).
1458
+ * Ton „err“ ist eine echte Fehlermeldung → role="alert" + aria-live="assertive";
1459
+ * def/ok bleiben role="status" + aria-live="polite" (wie im Doku-Markup).
1460
+ * Konsumiert nur bestehende Klassen.
1461
+ */
1462
+ declare class SnackbarComponent {
1463
+ /** Anzuzeigender Statustext. */
1464
+ readonly message: _angular_core.InputSignal<string>;
1465
+ /** Ton → .snack-def / .snack-ok / .snack-err */
1466
+ readonly tone: _angular_core.InputSignal<CdsSnackTone>;
1467
+ /** Optionaler Aktions-Button (.snack-act); leer = keiner. */
1468
+ readonly actionLabel: _angular_core.InputSignal<string>;
1469
+ /** Klick auf die optionale Aktion. */
1470
+ readonly action: _angular_core.OutputEmitterRef<void>;
1471
+ /** @internal */
1472
+ protected readonly classes: _angular_core.Signal<string>;
1473
+ /** @internal */
1474
+ protected readonly isError: _angular_core.Signal<boolean>;
1475
+ /**
1476
+ * Tonfarbe des Icons (wie im Doku-Markup).
1477
+ *
1478
+ * @internal
1479
+ */
1480
+ protected readonly iconStroke: _angular_core.Signal<string>;
1481
+ /**
1482
+ * Lucide-artiger Pfad je Ton (Glühbirne / Häkchen-Kreis / Ausrufezeichen-Kreis).
1483
+ *
1484
+ * @internal
1485
+ */
1486
+ protected readonly iconPath: _angular_core.Signal<string>;
1487
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SnackbarComponent, never>;
1488
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SnackbarComponent, "cds-snackbar", never, { "message": { "alias": "message"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "actionLabel": { "alias": "actionLabel"; "required": false; "isSignal": true; }; }, { "action": "action"; }, never, never, true, never>;
1489
+ }
1490
+
1491
+ /**
1492
+ * Testimonial — Wrapper um `.testimonial` aus css/components.css → „Testimonial Card“.
1493
+ *
1494
+ * Statische Zitat-Karte mit bereichsgefärbtem Top-Akzent (data-area), Quote-Icon
1495
+ * (.testimonial-icon, fill:currentColor), Zitat (blockquote) und Footer mit Name/Rolle.
1496
+ * Nur bestehende Klassen — kein eigenes CSS.
1497
+ */
1498
+ declare class TestimonialComponent {
1499
+ private readonly sanitizer;
1500
+ /** Zitattext. */
1501
+ readonly quote: _angular_core.InputSignal<string>;
1502
+ /** Name der zitierten Person. */
1503
+ readonly name: _angular_core.InputSignal<string>;
1504
+ /** Rolle/Funktion der zitierten Person (leer = keine Rollenzeile im Footer). */
1505
+ readonly roleLabel: _angular_core.InputSignal<string>;
1506
+ /** Markenbereich → data-area (Top-Akzent + Icon-Farbe). */
1507
+ readonly area: _angular_core.InputSignal<CdsArea>;
1508
+ /**
1509
+ * Zitat-Icon aus der zentralen Icon-Registry (icons.ts) statt dreifach
1510
+ * dupliziertem SVG-Pfad in Blockquote/Testimonial/TeamVoice.
1511
+ *
1512
+ * @internal
1513
+ */
1514
+ protected readonly quoteIcon: _angular_core.Signal<SafeHtml>;
1515
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TestimonialComponent, never>;
1516
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TestimonialComponent, "cds-testimonial", never, { "quote": { "alias": "quote"; "required": true; "isSignal": true; }; "name": { "alias": "name"; "required": true; "isSignal": true; }; "roleLabel": { "alias": "roleLabel"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1517
+ }
1518
+
1519
+ /**
1520
+ * TeamVoice — Wrapper um `.team-voice` aus css/components.css → „Team-Stimmen“.
1521
+ *
1522
+ * Editoriale Zitat-Reihe mit seitlichem Foto (im Grid abwechselnd links/rechts,
1523
+ * gesteuert per :nth-child innerhalb von `.team-voices`), bereichsgefärbtem
1524
+ * Akzent (data-area), Quote-Icon (ui-quote), Zitat und Name/Rolle. Mehrere
1525
+ * Komponenten in einen `<div class="team-voices">` legen, damit das alternierende
1526
+ * Layout greift (siehe Story).
1527
+ */
1528
+ declare class TeamVoiceComponent {
1529
+ private readonly sanitizer;
1530
+ /** Zitattext. */
1531
+ readonly quote: _angular_core.InputSignal<string>;
1532
+ /** Name der zitierten Person. */
1533
+ readonly name: _angular_core.InputSignal<string>;
1534
+ /** Rolle/Funktion der zitierten Person (leer = keine Rollenzeile). */
1535
+ readonly roleLabel: _angular_core.InputSignal<string>;
1536
+ /** Markenbereich → data-area (Akzentfarbe + Rahmen). */
1537
+ readonly area: _angular_core.InputSignal<CdsArea>;
1538
+ /** Bild-URL; leer = neutraler Platzhalter (Doku-Assets sind hier nicht eingebunden). */
1539
+ readonly image: _angular_core.InputSignal<string>;
1540
+ /** Alternativtext des Fotos. */
1541
+ readonly imageAlt: _angular_core.InputSignal<string>;
1542
+ /**
1543
+ * Zitat-Icon aus der zentralen Icon-Registry (icons.ts) statt dreifach
1544
+ * dupliziertem SVG-Pfad in Blockquote/Testimonial/TeamVoice.
1545
+ *
1546
+ * @internal
1547
+ */
1548
+ protected readonly quoteIcon: _angular_core.Signal<SafeHtml>;
1549
+ /**
1550
+ * Neutraler Inline-SVG-Platzhalter, damit Stories ohne externe Assets rendern.
1551
+ *
1552
+ * @internal
1553
+ */
1554
+ protected readonly placeholder = "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='600'%20height='450'%3E%3Crect%20width='600'%20height='450'%20fill='%23E8EDED'/%3E%3Ctext%20x='300'%20y='225'%20font-family='sans-serif'%20font-size='22'%20fill='%236E8585'%20text-anchor='middle'%20dominant-baseline='middle'%3ETeamfoto%3C/text%3E%3C/svg%3E";
1555
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TeamVoiceComponent, never>;
1556
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TeamVoiceComponent, "cds-team-voice", never, { "quote": { "alias": "quote"; "required": true; "isSignal": true; }; "name": { "alias": "name"; "required": true; "isSignal": true; }; "roleLabel": { "alias": "roleLabel"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "image": { "alias": "image"; "required": false; "isSignal": true; }; "imageAlt": { "alias": "imageAlt"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1557
+ }
1558
+
1559
+ /**
1560
+ * DownloadCta — Wrapper um `.cta-dl` aus css/components.css → „Download CTA“.
1561
+ *
1562
+ * Aufmerksamkeitsstarker Download-Block mit bereichsgefärbtem Top-Akzent + Icon
1563
+ * (data-area), Eyebrow/Titel/Beschreibung/Meta und zwei Aktionen (primär/sekundär,
1564
+ * über die bestehenden `.btn`-Klassen). Konsumiert nur vorhandene Styles.
1565
+ */
1566
+ declare class DownloadCtaComponent {
1567
+ /** Markenbereich → data-area (Top-Akzent, Icon-Tönung, Button-Farbe). */
1568
+ readonly area: _angular_core.InputSignal<CdsArea>;
1569
+ /** Kicker-Text oberhalb des Titels (leer = keine Eyebrow-Zeile). */
1570
+ readonly eyebrow: _angular_core.InputSignal<string>;
1571
+ /** Titel des Download-Angebots. */
1572
+ readonly title: _angular_core.InputSignal<string>;
1573
+ /** Beschreibungstext unterhalb des Titels (leer = keine Beschreibung). */
1574
+ readonly desc: _angular_core.InputSignal<string>;
1575
+ /** Zusatzinfo unterhalb der Beschreibung, z. B. Dateiformat/-größe (leer = keine Meta-Zeile). */
1576
+ readonly meta: _angular_core.InputSignal<string>;
1577
+ /** Beschriftung der primären Aktion. */
1578
+ readonly primaryLabel: _angular_core.InputSignal<string>;
1579
+ /** Beschriftung der sekundären Aktion (leer = ausgeblendet). */
1580
+ readonly secondaryLabel: _angular_core.InputSignal<string>;
1581
+ /** Klick auf die primäre Aktion (Haupt-CTA). */
1582
+ readonly primaryClick: _angular_core.OutputEmitterRef<MouseEvent>;
1583
+ /** Klick auf die sekundäre Aktion (nur wenn `secondaryLabel` gesetzt ist). */
1584
+ readonly secondaryClick: _angular_core.OutputEmitterRef<MouseEvent>;
1585
+ /**
1586
+ * Accessible Name der primären Aktion (cta-verwendung.mdx „Barrierefreiheit“: Button-Label
1587
+ * muss Ressource und Format nennen). Der sichtbare Button-Text bleibt `primaryLabel`
1588
+ * (meist knapp, z. B. „Herunterladen“) — er selbst nennt kein Ziel, der Titel steht nur
1589
+ * visuell daneben (`<h3 class="cta-dl-title">`) und erreicht den Accessible Name nicht.
1590
+ * Wer per Button-Liste navigiert, hört sonst nur die generische Aktion ohne Bezug.
1591
+ * Muster wie bei `PillComponent.computedAriaLabel`/Combobox-Remove-Buttons: „Aktion: Ziel“,
1592
+ * Format/Größe aus `meta` in Klammern angehängt, sofern gesetzt.
1593
+ *
1594
+ * @internal
1595
+ */
1596
+ protected readonly primaryAriaLabel: _angular_core.Signal<string>;
1597
+ /** Analog zu `primaryAriaLabel`, für die sekundäre Aktion.
1598
+ *
1599
+ * @internal
1600
+ */
1601
+ protected readonly secondaryAriaLabel: _angular_core.Signal<string>;
1602
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DownloadCtaComponent, never>;
1603
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DownloadCtaComponent, "cds-download-cta", never, { "area": { "alias": "area"; "required": false; "isSignal": true; }; "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "desc": { "alias": "desc"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "primaryLabel": { "alias": "primaryLabel"; "required": true; "isSignal": true; }; "secondaryLabel": { "alias": "secondaryLabel"; "required": false; "isSignal": true; }; }, { "primaryClick": "primaryClick"; "secondaryClick": "secondaryClick"; }, never, never, true, never>;
1604
+ }
1605
+
1606
+ /**
1607
+ * Section (`[cdsSection]`) — Wrapper um `.ep-section` aus css/components.css
1608
+ * (css/components.css:1223–1253, mobiler Innenabstand: Zeile 1228) mit dem optionalen
1609
+ * Kopf-Trio `.ep-section-label` (Kicker) / `.ep-section-h2` (Überschrift) /
1610
+ * `.ep-section-sub` (Lead). Das strukturelle Grundgerüst, in dem auf den
1611
+ * Beispielseiten praktisch jeder andere Baustein sitzt (133 Vorkommen, 85 davon mit
1612
+ * Kopfzeile).
1613
+ *
1614
+ * Alle drei Textteile sind Beiwerk (`input('')`): eine Sektion besteht auch ganz ohne
1615
+ * Kopf, nur aus ihrem projizierten Inhalt (docs/index.html:9378). Der Inhalt selbst
1616
+ * kommt per `<ng-content>` und ist deshalb kein Input.
1617
+ *
1618
+ * **Entscheidung 1 — Attributselektor, der Konsument wählt `<section>` oder `<div>`.**
1619
+ * Erste Fassung war `cds-section` als eigenes Element, das intern selbst entschied:
1620
+ * `<section aria-labelledby="…">`, wenn ein zugänglicher Name verfügbar war, sonst ein
1621
+ * namenloses `<div>`. Das setzte voraus, dass ein `background` auf einem
1622
+ * UMSCHLIESSENDEN Element sitzen musste (siehe Entscheidung 2) — gemessen im laufenden
1623
+ * Storybook (siehe `docs/adr/0008-selektortyp-der-wrapper-komponenten.md`, „Fall 2“):
1624
+ * `getComputedStyle(host).backgroundColor` und `host.getBoundingClientRect()`
1625
+ * meldeten beide „passt“, der Screenshot zeigte trotzdem keine gemalte Fläche — ein
1626
+ * unbekanntes Custom Element ohne eigene Inline-Inhalte, dessen einziges Kind als Block
1627
+ * herausgebrochen wird, hat keine eigene Box zum Malen.
1628
+ *
1629
+ * Die Komponente hängt sich deshalb als Attribut an ein vom Konsumenten geschriebenes
1630
+ * `<section>` oder `<div>`, analog zu `cds-icon-card`
1631
+ * (`icon-card/icon-card.component.ts`). Der Konsument entscheidet über das Tag, ob die
1632
+ * Sektion überhaupt eine `<section>`-Landmark werden KANN; die Komponente entscheidet
1633
+ * nur noch, ob sie `aria-labelledby` setzt (die eigene, gerenderte `.ep-section-h2` hat
1634
+ * Vorrang, sonst — wenn `heading` leer bleibt — die per `labelledBy` übergebene id einer
1635
+ * Überschrift außerhalb der Komponente). Schreibt der Konsument `<section cdsSection>`
1636
+ * ohne Namen, bleibt es bei einer `<section>` ohne `aria-labelledby`: HTML-AAM gibt ihr
1637
+ * dann keine Landmark-Rolle, aber das ist eine Entscheidung des Konsumenten, keine der
1638
+ * Komponente — sie erzwingt kein Tag mehr.
1639
+ *
1640
+ * **Entscheidung 2 — kein `background`-Input, die Fläche darf jetzt aber am Host
1641
+ * sitzen.** Das Mockup setzt Sektionsflächen inline (`style="background:var(--bg-surface)"`
1642
+ * / `--co-50` / …). Das ist der Flächen-Rhythmus zwischen aufeinanderfolgenden
1643
+ * Sektionen einer SEITE (Begründung inkl. Messwerten in docs/index.html:1450, „Warum
1644
+ * nicht die Sektion senken?“) — eine Entscheidung, die nur die Seite treffen kann, weil
1645
+ * nur sie ihre Nachbar-Sektionen kennt. Ein Bauteil kennt seinen Kontext nicht
1646
+ * (CONTRIBUTING.md §7) und bekäme mit einem `background`-Input eine Zuständigkeit, die
1647
+ * ihm nicht zusteht. Der Konsument setzt die Fläche deshalb weiterhin selbst — jetzt
1648
+ * aber direkt auf dem Element, das `cdsSection` trägt (`<section cdsSection
1649
+ * style="background:…">` bzw. `<div cdsSection style="…">`), denn dieses Element IST
1650
+ * `.ep-section`, kein Host mehr davor. Das umschließende Element aus der ersten Fassung
1651
+ * ist damit nicht mehr nötig (siehe Story „Fläche am Host“).
1652
+ */
1653
+ declare class SectionComponent {
1654
+ /** Kicker-Text über der Überschrift (`.ep-section-label`, leer = keine Kopfzeile). */
1655
+ readonly label: _angular_core.InputSignal<string>;
1656
+ /** Sektions-Überschrift (`.ep-section-h2`, leer = keine Überschrift). */
1657
+ readonly heading: _angular_core.InputSignal<string>;
1658
+ /** Lead-Text unter der Überschrift (`.ep-section-sub`, leer = kein Lead). */
1659
+ readonly sub: _angular_core.InputSignal<string>;
1660
+ /** Markenbereich → `.t-{area}` auf dem Label (Mockup: `class="ep-section-label t-co"`). */
1661
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
1662
+ /**
1663
+ * Id einer Überschrift AUSSERHALB der Komponente, die als zugänglicher Name dient,
1664
+ * wenn `heading` leer bleibt (siehe Entscheidung 1 in der Klassendoku).
1665
+ */
1666
+ readonly labelledBy: _angular_core.InputSignal<string>;
1667
+ private readonly instance;
1668
+ /** @internal */
1669
+ protected readonly headingId: string;
1670
+ /**
1671
+ * Zugänglicher Name der Sektion: die eigene Überschrift hat Vorrang, sonst die von
1672
+ * außen übergebene id. `null`, wenn keins von beidem vorhanden ist — dann setzt die
1673
+ * Komponente kein `aria-labelledby`. Ob der Host dadurch eine Landmark wird, hängt
1674
+ * am Tag, das der Konsument gewählt hat (siehe Entscheidung 1 in der Klassendoku).
1675
+ *
1676
+ * @internal
1677
+ */
1678
+ protected readonly ariaLabelledBy: _angular_core.Signal<string | null>;
1679
+ /** @internal */
1680
+ protected readonly labelClasses: _angular_core.Signal<string>;
1681
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SectionComponent, never>;
1682
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SectionComponent, "section[cdsSection], div[cdsSection]", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "sub": { "alias": "sub"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "labelledBy": { "alias": "labelledBy"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1683
+ }
1684
+
1685
+ /**
1686
+ * HeroImage (cds-hero-image) — Wrapper um `.hero-image` aus css/components.css
1687
+ * (css/components.css:851–878) mit optionaler Caption als Gradient-Overlay
1688
+ * (`-caption`, `-caption-eyebrow`, `-caption-title`, `-caption-text`). Vollbreites,
1689
+ * randloses `<figure>` im 21:9-Format, der Standard-Hero auf allen Customer-Pages
1690
+ * (17 Vorkommen in den Beispielseiten). Semantisch ein figure/figcaption-Pattern:
1691
+ * `alt` trägt die faktische Bildbeschreibung, die Caption die redaktionelle
1692
+ * Einordnung (Eyebrow, Titel, Text) — beide sollen sich nach `docs/index.html`
1693
+ * (Abschnitt „In-Article Figure“, dasselbe Prinzip) nicht inhaltlich decken.
1694
+ *
1695
+ * **Entscheidung 1 — kein `<figcaption>` ohne Textinhalt.** Bleiben `eyebrow`,
1696
+ * `heading` und `text` alle leer, entfällt das `<figcaption>`-Element vollständig
1697
+ * statt leer zu rendern (Variante „Hero ohne Caption“, siehe
1698
+ * `storybook-angular/src/docs/seitenmuster/wissensbeitrag.mdx` Abschnitt „Aufbau“,
1699
+ * Zeile 3: Beitrags-Heros zeigen das visuelle Versprechen ohne Marketing-Overlay).
1700
+ * Ein leeres `<figcaption>` wäre totes Markup ohne Zugänglichkeitsnutzen.
1701
+ *
1702
+ * **Entscheidung 2 — `headingLevel` statt fest verdrahtetem `<h1>`.** Das Mockup
1703
+ * (`docs/index.html:9412` u. a.) rendert `.hero-image-caption-title` durchgehend als
1704
+ * `<h1>`, weil der Hero dort das erste Überschriften-Element der Seite ist. Sitzt
1705
+ * der Hero dagegen unter einem eigenen `<h1>` — der Wissensbeitrag hat seinen
1706
+ * Titel bereits im Article-Header (`.article-title`, ebenfalls `<h1>`) —, entstünde
1707
+ * mit einem zweiten `<h1>` eine doppelte Top-Überschrift. `headingLevel` (Default
1708
+ * `1`) macht die Ebene explizit, `.hero-image-caption-title` ist reine CSS-Klasse
1709
+ * und trägt keine Heading-Semantik, das Styling bleibt in beiden Fällen identisch.
1710
+ *
1711
+ * **Entscheidung 3 — `objectPosition` als Style-Binding, die eine Ausnahme von
1712
+ * Spec-Randbedingung 6.** Der Bildausschnitt ist eine Eigenschaft des konkreten
1713
+ * Bildes (Motiv, Kopfposition), nicht der Seite — anders als z. B. eine
1714
+ * Sektionsfläche, die vom Seitenkontext abhängt. `docs/index.html` setzt ihn
1715
+ * deshalb an jedem Hero individuell direkt am `<img>` (z. B. `object-position:center
1716
+ * 70%`, Zeile 2640). Ohne diesen Input wäre die Komponente für Porträt-lastige
1717
+ * Motive unbrauchbar: `object-fit:cover` beschneidet das Bild sobald der
1718
+ * `max-height`-Cap greift (siehe `.hero-image-media`), und ohne Steuerung landet
1719
+ * der Ausschnitt zufällig in der Bildmitte. Als Style-Binding am `<img>`, nicht als
1720
+ * Klasse — es gibt in der CSS-Schicht keine Modifier-Klassen dafür, nur den
1721
+ * Inline-Weg, den das Mockup selbst nutzt.
1722
+ *
1723
+ * **Entscheidung 4 — `tabindex`/`id` sind nicht Teil der Komponente.** Das Mockup
1724
+ * setzt beides am `<figure>` (`id="ep-landing-main" tabindex="-1"`, z. B. Zeile
1725
+ * 9406) als Sprungziel des Skip-Links. Das Sprungziel ist eine Entscheidung der
1726
+ * Seite (welches Element „Hauptinhalt“ ist, hängt vom Seitenaufbau ab, nicht vom
1727
+ * Hero selbst), deshalb setzt der Konsument beides am `<cds-hero-image>`-Host.
1728
+ * Damit dieses Sprungziel eine eigene Box hat, ist der Host per
1729
+ * `:host{display:block}` selbst ein Block (Muster wie `cds-footer-main`): Als
1730
+ * unbekanntes Element wäre er `display:inline` mit herausgebrochenem Block-Kind
1731
+ * und hätte keine brauchbare Box für Fokus und Scroll-Position (ADR-0008, Fall 2).
1732
+ */
1733
+ declare class HeroImageComponent {
1734
+ /** Bildquelle. */
1735
+ readonly src: _angular_core.InputSignal<string>;
1736
+ /** Alternativtext — Pflicht, das Bild trägt Bedeutung (kein dekoratives Hero-Bild). */
1737
+ readonly alt: _angular_core.InputSignal<string>;
1738
+ /** Eyebrow-Zeile über dem Titel (`.hero-image-caption-eyebrow`, leer = keine Zeile). */
1739
+ readonly eyebrow: _angular_core.InputSignal<string>;
1740
+ /** Titel der Caption (`.hero-image-caption-title`, leer = kein Titel). */
1741
+ readonly heading: _angular_core.InputSignal<string>;
1742
+ /** Text unter dem Titel (`.hero-image-caption-text`, leer = kein Text). */
1743
+ readonly text: _angular_core.InputSignal<string>;
1744
+ /**
1745
+ * Heading-Ebene des gerenderten Titels: `1`, wenn der Hero die erste Überschrift
1746
+ * der Seite trägt (Standard auf Customer-Pages), `2`, wenn er unter einem
1747
+ * eigenen `<h1>` sitzt (Beitrags-Hero unter dem Article-Header, siehe
1748
+ * Entscheidung 2 in der Klassendoku).
1749
+ */
1750
+ readonly headingLevel: _angular_core.InputSignal<1 | 2>;
1751
+ /**
1752
+ * `loading`-Strategie des Bildes: `true` (Standard) rendert `loading="eager"`,
1753
+ * weil der Hero auf Customer-Pages immer above the fold sitzt. `false` für einen
1754
+ * zweiten, weiter unten liegenden Hero (z. B. innerhalb einer Bildstrecke).
1755
+ */
1756
+ readonly eager: _angular_core.InputSignal<boolean>;
1757
+ /**
1758
+ * `object-position` direkt am `<img>` (z. B. `'center 70%'`), siehe Entscheidung 3
1759
+ * in der Klassendoku. Leer = Browser-Default `center center`.
1760
+ */
1761
+ readonly objectPosition: _angular_core.InputSignal<string>;
1762
+ /**
1763
+ * Ob die Caption gerendert wird: nur, wenn mindestens einer der drei Textteile
1764
+ * gesetzt ist (siehe Entscheidung 1 in der Klassendoku).
1765
+ *
1766
+ * @internal
1767
+ */
1768
+ protected readonly hasCaption: _angular_core.Signal<boolean>;
1769
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<HeroImageComponent, never>;
1770
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HeroImageComponent, "cds-hero-image", never, { "src": { "alias": "src"; "required": true; "isSignal": true; }; "alt": { "alias": "alt"; "required": true; "isSignal": true; }; "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "text": { "alias": "text"; "required": false; "isSignal": true; }; "headingLevel": { "alias": "headingLevel"; "required": false; "isSignal": true; }; "eager": { "alias": "eager"; "required": false; "isSignal": true; }; "objectPosition": { "alias": "objectPosition"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1771
+ }
1772
+
1773
+ /**
1774
+ * Stoerer (cds-stoerer) — eine Kachel für `<cds-stoerer-set>`, Wrapper um `.stoerer`
1775
+ * aus css/components.css (css/components.css:926–974): Typ-Glyph + Thema-Label
1776
+ * (`.stoerer-topic`), Titel über zwei Zeilen (`.stoerer-title`), Meta-Zeile
1777
+ * (`.stoerer-meta`). Die ganze Kachel ist ein `<a>` — Klick auf die Fläche navigiert,
1778
+ * kein Div mit Klick-Handler.
1779
+ *
1780
+ * **Nur innerhalb von `<cds-stoerer-set>` verwendbar.** Diese Komponente rendert ihr
1781
+ * Markup nicht in sich selbst, sondern in ein internes `<ng-template>` und stellt es
1782
+ * dem Set als `TemplateRef` bereit (Begründung: Entscheidung 1 in der Klassendoku von
1783
+ * `StoererSetComponent`, `stoerer-set.component.ts`) — dasselbe Muster wie
1784
+ * `AreaTabComponent` für `cds-area-tabs` (`area-tabs/area-tab.component.ts`). Ohne
1785
+ * umgebendes `<cds-stoerer-set>` bleibt eine Kachel deshalb unsichtbar: Angular hängt
1786
+ * projizierten Inhalt ohne passendes `<ng-content>`-Ziel nicht ins DOM.
1787
+ *
1788
+ * **Entscheidung — Icon als projizierter Inhalt.** Wie in Ticket 05 (`cds-icon-card`,
1789
+ * `.scratch/angular-seitenbausteine/issues/05-icon-karte.md`, Abschnitt „Entscheidung:
1790
+ * Icon als projizierter Inhalt“) sind die Störer-Icons im Mockup wechselnde
1791
+ * Heroicons, keine DS-Bereichsglyphen aus der Registry — Inhalt, nicht Chrom. Deshalb
1792
+ * Projektion über `<ng-content select="[cdsIcon]">` statt eines `icon`-Inputs.
1793
+ * Abweichend von Ticket 05 trägt das projizierte `<svg>` die Klasse `stoerer-icon`
1794
+ * selbst (zusätzlich zu `cdsIcon`, `viewBox`, `aria-hidden="true"`,
1795
+ * `focusable="false"`): `.ep-card-icon` ist dort ein Container, der die Größe per
1796
+ * Nachfahren-Selektor (`.ep-card-icon svg`) an ein unverändertes Kind durchreicht.
1797
+ * `.stoerer-icon` (css/components.css:974) sitzt dagegen direkt auf dem SVG als
1798
+ * Flex-Kind von `.stoerer-topic` — es gibt keinen Container, der die Klasse
1799
+ * stellvertretend tragen könnte, ohne ein neues CSS-Selektorpaar zu erfinden
1800
+ * (verboten, ADR-0001). Der vollständige Kontrakt steht zusätzlich in der Story.
1801
+ */
1802
+ declare class StoererComponent {
1803
+ /** Thema/Inhaltstyp neben dem Icon (`.stoerer-topic`, z. B. „Nächste Veranstaltung“). */
1804
+ readonly topic: _angular_core.InputSignal<string>;
1805
+ /** Titel des verlinkten Inhalts — redaktionell auf zwei Zeilen gekürzt. */
1806
+ readonly title: _angular_core.InputSignal<string>;
1807
+ /** Linkziel; die Kachel ist vollständig klickbar. */
1808
+ readonly href: _angular_core.InputSignal<string>;
1809
+ /** Meta-Text nach dem Datum (Ort/Lesezeit/Format), leer = kein Meta-Text. */
1810
+ readonly meta: _angular_core.InputSignal<string>;
1811
+ /** ISO-Datum (`JJJJ-MM-TT`) → `<time datetime>`, gerendert vor `meta`, leer = kein Datum. */
1812
+ readonly date: _angular_core.InputSignal<string>;
1813
+ /**
1814
+ * Kachel-Markup als Template, das `cds-stoerer-set` per `ngTemplateOutlet` in sein
1815
+ * eigenes `<li>` einsetzt (siehe Klassendoku).
1816
+ *
1817
+ * @internal
1818
+ */
1819
+ readonly content: _angular_core.Signal<TemplateRef<unknown>>;
1820
+ /** @internal */
1821
+ protected readonly hasMeta: _angular_core.Signal<boolean>;
1822
+ /**
1823
+ * `date` als deutsches Langdatum („3. Dezember 2026“), manuell aus den
1824
+ * ISO-Komponenten gebaut statt über `new Date(iso)`: Ein reines Datums-ISO-String
1825
+ * wird von der Date-API als UTC-Mitternacht gelesen, `Intl.DateTimeFormat`
1826
+ * formatiert aber in der lokalen Zeitzone — in Zonen westlich von UTC kippt das
1827
+ * angezeigte Datum sonst einen Tag zurück.
1828
+ *
1829
+ * @internal
1830
+ */
1831
+ protected readonly formattedDate: _angular_core.Signal<string>;
1832
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StoererComponent, never>;
1833
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StoererComponent, "cds-stoerer", never, { "topic": { "alias": "topic"; "required": true; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "href": { "alias": "href"; "required": true; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "date": { "alias": "date"; "required": false; "isSignal": true; }; }, {}, never, ["[cdsIcon]"], true, never>;
1834
+ }
1835
+
1836
+ /**
1837
+ * StoererSet (cds-stoerer-set) — Wrapper um `.stoerer-set` / `.stoerer-list` aus
1838
+ * css/components.css (css/components.css:926–974): das Set aus ein bis drei
1839
+ * `<cds-stoerer>`-Kacheln, das auf der Startseite oben rechts über dem Hero-Bild
1840
+ * liegt. Der Positionsrahmen `.stoerer-hero` (umschließt Hero-Bild UND Set,
1841
+ * `container-type:inline-size` für die Container-Query-Schwelle) ist bewusst NICHT
1842
+ * Teil dieser Komponente, sondern bleibt beim Konsumenten (siehe
1843
+ * `.scratch/angular-seitenbausteine/issues/03-stoerer.md`): er umschließt Hero UND
1844
+ * Set gemeinsam, das könnte diese Komponente als internes Detail nicht leisten, ohne
1845
+ * das Hero-Bild selbst zu kennen.
1846
+ *
1847
+ * **Entscheidung — `<li>` ohne strukturelles Wrapper-Element.** `.stoerer-list` ist
1848
+ * ein `<ul>`; nach HTML-AAM bekommt ein `<li>` die implizite Rolle `listitem` nur als
1849
+ * direktes Kind eines `<ul>`/`<ol>`/`<menu>` — Screenreader kündigen die Liste sonst
1850
+ * nicht mit Anzahl an. Ein einfaches `<ng-content>` hätte `<cds-stoerer>` selbst
1851
+ * zwischen `<ul>` und `<li>` geschoben (kein direktes Kind mehr), und ein
1852
+ * `display:contents`-Wrapper verbietet sich als neues CSS (ADR-0001). Gelöst über
1853
+ * dasselbe Muster, das `cds-area-tabs`/`cds-area-tab` bereits für „projizierte
1854
+ * Kind-Komponente, deren Markup an einer selbst bestimmten Stelle im eigenen Template
1855
+ * landet“ etabliert (`area-tabs/area-tabs.component.ts`): `cds-stoerer` rendert nicht
1856
+ * in sich selbst, sondern in ein `<ng-template>` und liefert es als `TemplateRef`
1857
+ * (`stoerer.component.ts`). Diese Komponente liest die projizierten `<cds-stoerer>`
1858
+ * über `contentChildren()` und setzt ihr Template per `ngTemplateOutlet` direkt in
1859
+ * ein selbst gerendertes `<li>` ein. Im laufenden Storybook geprüft (`Komponenten/Hero/
1860
+ * Störer` → Story „Interaktiv“, DOM live im Browser per `querySelector` abgefragt,
1861
+ * zusätzlich in der Play-Funktion der Story gepinnt): `<ul class="stoerer-list">`
1862
+ * hat ausschließlich `<li>` als direkte Kinder (`ul.stoerer-list > *` → `["LI","LI"]`),
1863
+ * `<cds-stoerer>` selbst taucht im gerenderten DOM nirgends auf — Angular hängt
1864
+ * unprojizierten Content ohne passendes `<ng-content>`-Ziel gar nicht erst ein, exakt
1865
+ * wie bei `<cds-area-tab>` innerhalb von `<cds-area-tabs>`. Ein `items`-Array (die im
1866
+ * Ticket vermerkte Alternative) hätte denselben DOM-Baum ergeben, aber den
1867
+ * Konsumenten gezwungen, das projizierte Icon jeder Kachel in ein Datenobjekt
1868
+ * umzuziehen; mit dieser Lösung bleibt die deklarative, Content-projizierende API
1869
+ * erhalten.
1870
+ */
1871
+ declare class StoererSetComponent {
1872
+ /** Zugänglicher Name des Sets (`<aside aria-label>`); „Aktuelles“ wie im Mockup. */
1873
+ readonly label: _angular_core.InputSignal<string>;
1874
+ /**
1875
+ * Die Kacheln kommen als projizierte `<cds-stoerer>`-Kinder.
1876
+ *
1877
+ * @internal
1878
+ */
1879
+ protected readonly tiles: _angular_core.Signal<readonly StoererComponent[]>;
1880
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StoererSetComponent, never>;
1881
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StoererSetComponent, "cds-stoerer-set", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, ["tiles"], never, true, never>;
1882
+ }
1883
+
1884
+ /**
1885
+ * LinkCard (cds-link-card) — Wrapper um `a.card.card-elevated` aus css/components.css
1886
+ * (css/components.css:147–154) samt `.card-cta-link` (css/components.css:1347–1356).
1887
+ *
1888
+ * Die Lücke, die `CardComponent` bewusst offen lässt (siehe deren Klassendoku):
1889
+ * `.card-elevated` wirkt im CSS ausschließlich auf `a.card-elevated` (Riegel aus
1890
+ * `CONTRIBUTING.md` §4, „Elevation = Interaktivität“) — eine `<article>`/`<div>`-Karte
1891
+ * bekommt den Schatten auch mit gesetzter Klasse nicht. Diese Komponente rendert
1892
+ * deshalb ein echtes `<a>`, die ganze Fläche ist der Link, kein Klick-Handler auf
1893
+ * einem nicht-interaktiven Element.
1894
+ *
1895
+ * Struktur wie `CardComponent`: optionale bereichsgefärbte `.card-media` mit der
1896
+ * echten Bereichs-Glyphe, `.card-body` mit `.card-eyebrow` / `.card-title` /
1897
+ * `.card-text`. Neu ist der Fuß `.card-cta-link`, optional unten angeheftet
1898
+ * (`--pinned`, für gleich hohe Karten im Raster über `.card-body{flex:1}`).
1899
+ *
1900
+ * **Entscheidung — Fuß ist ein `<span>`, kein zweites `<a>`.** Die ganze Karte ist
1901
+ * bereits `a.card-elevated`; ein verschachteltes `<a>` im Fuß wäre ungültiges HTML
1902
+ * (der Browser schließt es beim Parsen vorzeitig) und würde zwei Klickziele auf
1903
+ * derselben Fläche erzeugen. `docs/index.html:4707–4716` zeigt exakt dieses Muster:
1904
+ * `<span class="card-cta-link card-cta-link--pinned">…</span>` innerhalb von
1905
+ * `a.card.card-elevated`. `.card-cta-link` selbst ist nicht auf `a.` gescoped (anders
1906
+ * als `.card-elevated`), der Span trägt Farbe und Typografie also unverändert.
1907
+ *
1908
+ * **Entscheidung — Pfeil-Suffix wird von der Komponente ergänzt, nicht Teil von
1909
+ * `ctaLabel`.** Der Pfeil ist reine visuelle Affordanz, kein Inhalt — `docs/index.html`
1910
+ * (Abschnitt „Klickbare Karte“) kapselt ihn deshalb selbst in ein
1911
+ * `aria-hidden`-Span. Läge das Zeichen im `ctaLabel`-Text, müsste jeder Aufrufer
1912
+ * selbst an das `aria-hidden` denken; das wird hier stattdessen einmalig in der
1913
+ * Komponente erledigt.
1914
+ *
1915
+ * **Entscheidung — kein `data-area` auf `.card-cta-link`.** Die Doku hält die
1916
+ * CTA-Farbe in gemischten Bereichs-Listen bewusst einheitlich Corporate-Petrol
1917
+ * (`docs/index.html:8762`: „CTA-Farbe einheitlich `--co-700`“), unabhängig vom
1918
+ * `area` der Karte. Der Fuß bleibt deshalb ohne `data-area`-Bindung.
1919
+ *
1920
+ * **Entscheidung — Host als Flex-Container.** Im Raster ist der Host das
1921
+ * Grid-Kind, das `align-items:stretch` auf Zeilenhöhe zieht, nicht `a.card`. Ohne
1922
+ * eigene Regel blieb die Karte auf Inhaltshöhe, und eine Karte ohne Eyebrow endete
1923
+ * samt `--pinned`-Fuß höher als ihre Nachbarn. `:host{display:flex}` mit
1924
+ * `flex:1` an der Karte gibt die gestreckte Höhe an `a.card` weiter; Story
1925
+ * „Im Raster“ pinnt das.
1926
+ */
1927
+ declare class LinkCardComponent {
1928
+ private readonly sanitizer;
1929
+ /** Kartentitel. */
1930
+ readonly title: _angular_core.InputSignal<string>;
1931
+ /** Anreißer-/Beschreibungstext der Karte. */
1932
+ readonly text: _angular_core.InputSignal<string>;
1933
+ /** Linkziel; die ganze Kartenfläche ist klickbar. */
1934
+ readonly href: _angular_core.InputSignal<string>;
1935
+ /** Kicker-Text oberhalb des Titels (`.card-eyebrow`, leer = keine Eyebrow-Zeile). */
1936
+ readonly eyebrow: _angular_core.InputSignal<string>;
1937
+ /** Markenbereich → `data-area` (färbt Media-Glyphe + Eyebrow). */
1938
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
1939
+ /** Bereichsgefärbte Medienfläche mit Bereichs-Glyphe anzeigen. */
1940
+ readonly showMedia: _angular_core.InputSignal<boolean>;
1941
+ /** Fuß-Link-Text (`.card-cta-link`, leer = kein Fuß). */
1942
+ readonly ctaLabel: _angular_core.InputSignal<string>;
1943
+ /** Fuß unten an die Kartenunterkante anheften (`.card-cta-link--pinned`, für gleich hohe Karten im Raster). */
1944
+ readonly ctaPinned: _angular_core.InputSignal<boolean>;
1945
+ /**
1946
+ * Echte Bereichs-Glyphe aus icons/icons.js, als ico-48-SVG in die Media-Fläche —
1947
+ * identisch zu `CardComponent.mediaSvg`.
1948
+ *
1949
+ * @internal
1950
+ */
1951
+ protected readonly mediaSvg: _angular_core.Signal<SafeHtml>;
1952
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LinkCardComponent, never>;
1953
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LinkCardComponent, "cds-link-card", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "text": { "alias": "text"; "required": true; "isSignal": true; }; "href": { "alias": "href"; "required": true; "isSignal": true; }; "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "showMedia": { "alias": "showMedia"; "required": false; "isSignal": true; }; "ctaLabel": { "alias": "ctaLabel"; "required": false; "isSignal": true; }; "ctaPinned": { "alias": "ctaPinned"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1954
+ }
1955
+
1956
+ /**
1957
+ * FeaturedCard (cds-featured-card) — Wrapper um `.card-featured` aus
1958
+ * css/components.css (css/components.css:230–249): die horizontale Großkarte für
1959
+ * **genau einen** hervorgehobenen Beitrag oder Termin (Bild links 60 %, Textspalte
1960
+ * rechts 40 % als absolut positioniertes Overlay), siehe `docs/index.html`
1961
+ * Abschnitt „Featured · horizontale Großkarte“ (`#gt-events-featured`).
1962
+ *
1963
+ * **Entscheidung 1 — `href` entscheidet zwischen `<a>` und `<article>`.** Die
1964
+ * Doku-Beispiele zeigen die Featured-Card ausschließlich als Link
1965
+ * (`a.card.card-elevated.card-featured`), das Ticket verlangt aber ausdrücklich eine
1966
+ * Variante ohne `<a>`. `.card-elevated` ist nach `CONTRIBUTING.md` §4 („Elevation =
1967
+ * Interaktivität“) im CSS auf `a.card-elevated` gescoped — eine `<article>` bekäme
1968
+ * den Schatten mit gesetzter Klasse ohnehin nicht. Die Komponente führt die Klasse
1969
+ * deshalb nur mit, wenn sie auch wirkt: mit `href` ein `<a class="card card-elevated
1970
+ * card-featured">`, ohne `href` ein `<article class="card card-featured">` (ruht
1971
+ * flach mit dem `--bd-strong`-Rahmen aus `.card`, wie jede statische Fläche). Media
1972
+ * und Body stehen dafür einmal in einem gemeinsamen `<ng-template>` und werden in
1973
+ * beiden Zweigen per `<ng-container [ngTemplateOutlet]>` eingesetzt — dasselbe
1974
+ * Muster wie `SectionComponent` (`section.component.ts`) für „zwei Wurzelelemente,
1975
+ * ein Körper“. `<ng-container>` rendert selbst kein Element, die Kindselektoren aus
1976
+ * Entscheidung 2 bleiben also unberührt: im laufenden Storybook erneut per
1977
+ * `querySelector`/`getBoundingClientRect` gemessen (siehe Play-Funktionen), Ergebnis
1978
+ * unverändert zur vorherigen, noch duplizierten Fassung.
1979
+ *
1980
+ * **Entscheidung 2 — die Pill ist direkt komponiertes Markup, kein `<cds-pill>`.**
1981
+ * Das CSS arbeitet mit direkten Kindselektoren: `.card-featured>.card-media`,
1982
+ * `.card-featured-body>.pill`, `.card-featured-body>.card-text`,
1983
+ * `.card-featured-body>.card-title-hero` (jeweils mit `margin`/`min-height`/
1984
+ * `line-clamp`-Übernahmen, siehe CSS-Kommentare dort). `<cds-pill>` rendert sein
1985
+ * `.pill`-`<span>` nicht auf dem eigenen Host-Element, sondern eine Ebene tiefer
1986
+ * (`pill.component.ts`: Host ist `<cds-pill>`, `.pill` sitzt im Template darunter) —
1987
+ * projiziert als `<cds-pill class="pill">` stünde die Pille damit als
1988
+ * `.card-featured-body>cds-pill>.pill`, zwei Ebenen statt einer, und die
1989
+ * Kindselektoren griffen nicht mehr (leise: kein Fehler, nur falsches Layout).
1990
+ * Dieselbe Abwägung wie in `download-cta.component.ts` (Kommentar über den
1991
+ * Buttons): dort verhindert `.cta-dl-actions`, das seine Kinder per Flex streckt,
1992
+ * dass ein `<cds-button>`-Host mitstreckt; hier verhindert ein Kindselektor, dass
1993
+ * irgendein zusätzliches Host-Element dazwischentritt. In beiden Fällen werden die
1994
+ * Klassen direkt komponiert statt eine Wrapper-Komponente zu verwenden. Geprüft im
1995
+ * laufenden Storybook (`Komponenten/Cards & Teaser/Featured-Karte`): die gerenderte
1996
+ * Kette ist `.card-featured>.card-media` und `.card-featured-body` mit `.pill`,
1997
+ * `.card-text`, `.card-title-hero` als direkten Kindern, kein zusätzliches Element
1998
+ * dazwischen (siehe Play-Funktionen der Stories).
1999
+ *
2000
+ * Weil die Pille direkt komponiert wird, übernimmt diese Komponente auch die
2001
+ * `aria-label`-Regel von `PillComponent` (`pill.component.ts`) von Hand nach:
2002
+ * Default „Bereich `<pill>`“, überschreibbar über `pillAriaLabel` — nötig, weil die
2003
+ * Pille nicht immer einen Bereich benennt (siehe `pillAriaLabel`-Doku unten).
2004
+ *
2005
+ * **Entscheidung 3 — kein separates `data-area` für die Pille.** Die Doku setzt
2006
+ * Karte und Pille immer auf denselben Bereich (`docs/index.html:8979`: Karte
2007
+ * `data-area="es"`, Pille `data-area="es"`). Die Komponente bindet deshalb `area`
2008
+ * auf beide, statt einen zweiten Bereichs-Input zu erfinden.
2009
+ *
2010
+ * **Entscheidung 4 — kein CTA- und kein Meta-Input.** Die Doku-Vorlage zeigt
2011
+ * zusätzlich einen Meta-Strip (Datum/Ort/Format) und einen `.card-cta-link`-Fuß;
2012
+ * das Ticket benennt als API aber nur `title`/`text`/`imageSrc`/`imageAlt`/`href`/
2013
+ * `pill`/`area`. Diese Komponente bildet exakt diese Fläche ab, ohne Inputs zu
2014
+ * erfinden, die das Ticket nicht vorsieht — ein Meta-Strip oder ein CTA-Fuß wären
2015
+ * eine spätere, eigene Erweiterung.
2016
+ */
2017
+ declare class FeaturedCardComponent {
2018
+ /** Titel (`.card-title-hero`). */
2019
+ readonly title: _angular_core.InputSignal<string>;
2020
+ /** Anreißer-/Beschreibungstext (`.card-text`). */
2021
+ readonly text: _angular_core.InputSignal<string>;
2022
+ /** Bildquelle der 16:9-Medienfläche. */
2023
+ readonly imageSrc: _angular_core.InputSignal<string>;
2024
+ /** Alternativtext des Bildes — Pflicht, das Bild trägt Bedeutung. */
2025
+ readonly imageAlt: _angular_core.InputSignal<string>;
2026
+ /** Linkziel; gesetzt → `<a>` (ganze Fläche klickbar), leer → `<article>` (statisch, kein Schatten). */
2027
+ readonly href: _angular_core.InputSignal<string>;
2028
+ /** Bereichs-Pille über dem Titel (`.pill`, leer = keine Pille). */
2029
+ readonly pill: _angular_core.InputSignal<string>;
2030
+ /**
2031
+ * `aria-label` der Pille überschreiben; Default „Bereich `<pill>`“, wie
2032
+ * `PillComponent` (`pill.component.ts`). Nötig, weil `pill` nicht immer einen
2033
+ * Bereich benennt — das Mockup zeigt neben `aria-label="Bereich Corporate"` auch
2034
+ * `aria-label="Lesezeit 12 Minuten"` für dieselbe Klasse.
2035
+ */
2036
+ readonly pillAriaLabel: _angular_core.InputSignal<string | undefined>;
2037
+ /** Markenbereich → `data-area` auf Karte und Pille. */
2038
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
2039
+ /** @internal */
2040
+ protected readonly computedPillAriaLabel: _angular_core.Signal<string>;
2041
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FeaturedCardComponent, never>;
2042
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FeaturedCardComponent, "cds-featured-card", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "text": { "alias": "text"; "required": true; "isSignal": true; }; "imageSrc": { "alias": "imageSrc"; "required": true; "isSignal": true; }; "imageAlt": { "alias": "imageAlt"; "required": true; "isSignal": true; }; "href": { "alias": "href"; "required": false; "isSignal": true; }; "pill": { "alias": "pill"; "required": false; "isSignal": true; }; "pillAriaLabel": { "alias": "pillAriaLabel"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2043
+ }
2044
+
2045
+ /**
2046
+ * IconCard (`[cdsIconCard]`) — Wrapper um `.ep-card` aus css/components.css
2047
+ * (css/components.css:1298–1340): die Icon-Kachel mit farbiger Icon-Fläche, Eyebrow,
2048
+ * Titel, Text und optionaler Pfeil-CTA-Zeile, die auf den Beispielseiten Bereichs-
2049
+ * und Angebots-Einstiege trägt (`docs/index.html:9401–9420` u. a., 81 Vorkommen).
2050
+ *
2051
+ * **Entscheidung 1 — Attributselektor, kein Element-Selektor.** Erste Fassung dieser
2052
+ * Komponente war `cds-icon-card` als eigenes Element mit `href`-Input, das intern
2053
+ * zwischen `<a class="ep-card ep-card-link">` und `<div class="ep-card">` wählte
2054
+ * (`@if`/`@else` + `<ng-template>`). Gemessen im laufenden Storybook: zwei Karten mit
2055
+ * unterschiedlich langem Text ergaben im `.ep-cards`-Grid ungleiche `.ep-card`-Höhen
2056
+ * (174px/270px), weil `align-items:stretch` nur den unsichtbaren `<cds-icon-card>`-Host
2057
+ * streckt, nicht das `.ep-card`-Element eine Ebene darunter. Dieselbe Messung mit
2058
+ * `.ep-card` OHNE Host-Wrapper (rohes Markup direkt in `.ep-cards`) ergab 306px/306px,
2059
+ * CTA-Unterkanten auf identischer Y-Koordinate — das CSS gleicht die Höhen korrekt aus,
2060
+ * sobald `.ep-card` selbst das Grid-Kind ist. Der Fehler saß also im Wrapper-Element,
2061
+ * nicht in der CSS-Schicht (siehe „Im Raster“-Story, dort dieselbe Messung als
2062
+ * Play-Funktion gepinnt).
2063
+ *
2064
+ * Die Lösung, analog zu Angular Materials `a[mat-button], button[mat-button]`: die
2065
+ * Komponente hängt sich als Attribut an ein vom Konsumenten geschriebenes `<a>` oder
2066
+ * `<div>`, statt ein eigenes Element zu sein. Dadurch trägt **derselbe** native Knoten,
2067
+ * den der Konsument in sein Grid schreibt, sowohl die Komponentenlogik als auch die
2068
+ * `.ep-card`-Klasse — kein Host-Element dazwischen, `align-items:stretch` trifft direkt
2069
+ * auf `.ep-card`.
2070
+ *
2071
+ * **`href` ist deshalb kein Input mehr.** Ob die Karte ein Link ist, entscheidet der
2072
+ * Konsument über das gewählte Tag (`<a cdsIconCard href="…">` vs. `<div cdsIconCard>`)
2073
+ * und setzt `href` als natives Attribut direkt am `<a>` — Angular muss dafür nichts
2074
+ * verwalten. `.ep-card-link` (nur auf `a.ep-card-link` wirksam, `CONTRIBUTING.md` §4)
2075
+ * wird deshalb vom Host-Tag abgeleitet, nicht mehr per Verzweigung im Template
2076
+ * gerendert.
2077
+ *
2078
+ * **`.ep-card-link` hängt an `<a>` UND `href`, nicht am Tag allein.** Ein `<a
2079
+ * cdsIconCard>` ohne `href` ist weder fokussierbar noch hat es eine Link-Rolle —
2080
+ * `.ep-card-link` (Schatten, Hover-Anhebung, Cursor) nur am Tag festzumachen hätte
2081
+ * eine Karte erzeugt, die aussieht wie ein Link, aber keiner ist, und genau die
2082
+ * Garantie aufgegeben, die die frühere `href`-Input-Fassung strukturell hatte (leerer
2083
+ * String → zwingend der `<div>`-Zweig). `isLink()` prüft deshalb beides.
2084
+ *
2085
+ * **`isLink()` ist eine Methode im Host-Binding, kein einmalig berechnetes Feld.**
2086
+ * `href` kann nach dem Erstellen zur Laufzeit gesetzt/entfernt werden (z. B.
2087
+ * `<a cdsIconCard [attr.href]="urlSignal()">`). Ein Host-Binding-Ausdruck
2088
+ * (`'[class.ep-card-link]': 'isLink()'`) wird bei JEDEM Refresh der DECLARING VIEW
2089
+ * neu ausgewertet — also der Elternvorlage, die `<a cdsIconCard>` schreibt —, nicht
2090
+ * nur bei einem Refresh der eigenen (OnPush-gesteuerten) Kindvorlage dieser
2091
+ * Komponente. Das ist kein Sonderfall wie bei einem in ADR-0007 §3 verworfenen
2092
+ * Getter (dort ging es um einen Getter in einer INTERPOLATION der eigenen
2093
+ * Kindvorlage, die unter OnPush nur bei eigenen Signal-Änderungen neu läuft):
2094
+ * Host-Bindings werden unabhängig vom OnPush-Status der Komponente selbst
2095
+ * mitgeführt, wenn die Elternansicht aktualisiert wird — reagiert also auf
2096
+ * `[attr.href]`/`[href]`-Bindungen des Konsumenten, ob Signal- oder
2097
+ * Zone.js-getrieben, ohne `effect()` (ADR-0007 §4) und ohne `MutationObserver`.
2098
+ * Empirisch geprüft (Spike-Story mit `[attr.href]="signal()"`-Toggle zur Laufzeit,
2099
+ * seither wieder gelöscht): Setzen des Signals nach Erstrender schaltet
2100
+ * `.ep-card-link` zuverlässig um. Einzige Grenze: eine Änderung, die AUSSERHALB von
2101
+ * Angular direkt am nativen Element vorgenommen wird (z. B. `el.setAttribute
2102
+ * ('href', …)` von Fremdcode), löst keinen Refresh aus — das gilt aber für jede
2103
+ * Angular-Bindung gleichermaßen und ist kein Sonderfall dieser Komponente.
2104
+ *
2105
+ * **Entscheidung 2 — Icon als projizierter Inhalt, OHNE dass das SVG eine eigene
2106
+ * Größenklasse tragen muss.** Wie bei `cds-stoerer` (siehe dessen Klassendoku) sind
2107
+ * die Icons auf den Beispielseiten wechselnde Heroicons, keine DS-Bereichsglyphen aus
2108
+ * der Registry `icons/cds-icons.ts` — Inhalt, nicht Chrom. Deshalb Projektion über
2109
+ * `<ng-content select="[cdsIcon]">` statt eines `icon`-Strings. Anders als beim Störer
2110
+ * ist `.ep-card-icon` hier aber ein echter CONTAINER: css/components.css:1310+1318
2111
+ * setzt Maße und Stroke über den Nachfahren-Selektor `.ep-card-icon svg{width:32px;
2112
+ * height:32px;stroke-width:var(--icon-stroke-sm)}`, nicht über eine Klasse auf dem
2113
+ * SVG selbst. Der Konsument liefert deshalb ein unverändertes `<svg cdsIcon
2114
+ * viewBox="…" aria-hidden="true" focusable="false">…</svg>` OHNE zusätzliche Klasse —
2115
+ * das Verhältnis Größe/Stroke kommt allein aus dem Container. Geprüft an
2116
+ * css/components.css:1298–1318 (Kommentar dort: „Farbe kommt aus der Komponente,
2117
+ * nicht aus … inline gesetzten style-Attributen“) und in der Story „Interaktiv“
2118
+ * gepinnt (Play-Funktion misst die gerenderte SVG-Breite).
2119
+ *
2120
+ * **`data-area` sitzt auf drei Elementen** (`.ep-card` (Host), `.ep-card-icon`,
2121
+ * `.ep-card-eyebrow`, wie im Mockup, `docs/index.html:4681–4686`): die CTA-Farbe
2122
+ * braucht dagegen KEIN eigenes `data-area`, sie kommt über den Nachfahren-Selektor
2123
+ * `.ep-card[data-area="…"] .ep-card-cta` (css/components.css:1336–1339) vom
2124
+ * `data-area` der Karte selbst.
2125
+ *
2126
+ * **Kein erfundener `aria-label`.** Der Pfeil-Suffix der CTA-Zeile ist reine visuelle
2127
+ * Affordanz (`docs/index.html:4686`: `<span aria-hidden="true">→</span>`) und steht
2128
+ * deshalb `aria-hidden`, unverändert zum Mockup — kein zusätzlicher, selbst
2129
+ * ausgedachter zugänglicher Name.
2130
+ *
2131
+ * **Entscheidung 3 — kein `cdsIconCards`-Raster.** `.ep-cards` ist ein reines
2132
+ * `display:grid` ohne Struktur oder Verhalten (dieselbe Begründung wie beim Verzicht
2133
+ * auf einen `layout-grid`-Wrapper, siehe `spec.md`). Konsumenten schreiben
2134
+ * `<div class="ep-cards">` von Hand (siehe Story „Im Raster“).
2135
+ */
2136
+ declare class IconCardComponent {
2137
+ private readonly elementRef;
2138
+ /** Kartentitel (`.ep-card-title`). */
2139
+ readonly title: _angular_core.InputSignal<string>;
2140
+ /** Anreißer-/Beschreibungstext (`.ep-card-text`). */
2141
+ readonly text: _angular_core.InputSignal<string>;
2142
+ /** Kicker-Text oberhalb des Titels (`.ep-card-eyebrow`, leer = keine Eyebrow-Zeile). */
2143
+ readonly eyebrow: _angular_core.InputSignal<string>;
2144
+ /** Markenbereich → `data-area` auf Karte, Icon-Kachel und Eyebrow. */
2145
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
2146
+ /** CTA-Zeile am Kartenfuß (`.ep-card-cta`, leer = keine CTA-Zeile). */
2147
+ readonly ctaLabel: _angular_core.InputSignal<string>;
2148
+ /**
2149
+ * Ob der Host ein `<a>` MIT `href` ist → schaltet `.ep-card-link` (Schatten/Hover,
2150
+ * `CONTRIBUTING.md` §4). Als Methode im Host-Binding aufgerufen (nicht einmalig in
2151
+ * ein Feld geschrieben), damit ein zur Laufzeit gesetztes/entferntes `href` erkannt
2152
+ * wird — Begründung und Grenzen in der Klassendoku oben.
2153
+ *
2154
+ * @internal
2155
+ */
2156
+ protected isLink(): boolean;
2157
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconCardComponent, never>;
2158
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconCardComponent, "a[cdsIconCard], div[cdsIconCard]", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "text": { "alias": "text"; "required": true; "isSignal": true; }; "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "ctaLabel": { "alias": "ctaLabel"; "required": false; "isSignal": true; }; }, {}, never, ["[cdsIcon]"], true, never>;
2159
+ }
2160
+
2161
+ /**
2162
+ * Feature (`[cdsFeature]`) — Wrapper um `.ep-feature` aus css/components.css
2163
+ * (css/components.css:1363–1379): die flache Feature-Zeile ohne Box und ohne
2164
+ * Schatten (Icon-Kachel links, Titel/Text rechts) — die „Offene Feature-Liste“ der
2165
+ * Beispielseiten (Doku-Sektion `docs/index.html:4882` ff., Beispielseiten u. a.
2166
+ * `docs/index.html:10405–10415`, `11582–11588`; 40 Vorkommen als
2167
+ * `class="ep-feature col-4"` im `.layout-grid`).
2168
+ *
2169
+ * **Attributselektor, kein eigenes Element (ADR-0008).** Das Mockup setzt die
2170
+ * Spaltenklasse am selben Element wie `.ep-feature` (`class="ep-feature col-4"`).
2171
+ * Das Bauteil ist damit selbst Grid-Kind UND Ziel einer Layout-Klasse des
2172
+ * Konsumenten — exakt das Kriterium aus
2173
+ * [ADR-0008](../../../../../../docs/adr/0008-selektortyp-der-wrapper-komponenten.md).
2174
+ * Ein eigenes `<cds-feature>`-Element mit innerem `<div class="ep-feature">` würde
2175
+ * `.layout-grid>[class*="col-"]` (css/base.css:214) brechen: der `col-*`-Selektor
2176
+ * träfe den unsichtbaren Host, nicht `.ep-feature`, das `.layout-grid` gibt seinem
2177
+ * Kind (dem Host) dann zwar per `align-items:stretch` (Grid-Default) die volle
2178
+ * Zeilenhöhe, aber `.ep-feature` darunter bliebe auf Inhaltshöhe — derselbe Fehler,
2179
+ * den ADR-0008 Fall 1 für `.ep-card`/`.ep-cards` gemessen hat (174px/270px statt
2180
+ * 306px/306px). Die Komponente hängt sich deshalb als Attribut an ein vom
2181
+ * Konsumenten geschriebenes `<div>` (`<div cdsFeature class="col-4">`), analog zu
2182
+ * `cds-icon-card` (siehe dessen Klassendoku). Gemessen für dieses Bauteil in der
2183
+ * Story „Dreispalter“ (Play-Funktion): drei `.ep-feature` mit stark
2184
+ * unterschiedlich langem Text als `col-4`-Geschwister in einem `.layout-grid`
2185
+ * ergeben identische Höhen und deckungsgleiche Unterkanten (Messwerte in der
2186
+ * Story-Doku dort).
2187
+ *
2188
+ * **Icon-Kontrakt: `.ep-feature-icon` ist ein Container, keine Klasse auf dem
2189
+ * SVG — UND reicht zusätzlich die Farbe durch, anders als `.ep-card-icon`.** Wie
2190
+ * `.ep-card-icon` (siehe `icon-card.component.ts`, Entscheidung 2) setzt
2191
+ * css/components.css:1369 Maße und Stroke über den Nachfahren-Selektor
2192
+ * `.ep-feature-icon svg{width:26px;height:26px;stroke-width:var(--icon-stroke-md)}`
2193
+ * — NICHT über eine Klasse auf dem SVG selbst, anders als `.stoerer-icon`
2194
+ * (`stoerer.component.ts`), das direkt auf dem projizierten `<svg>` sitzt. Der
2195
+ * Konsument liefert deshalb ein unverändertes
2196
+ * `<svg cdsIcon viewBox="…" aria-hidden="true" focusable="false">…</svg>` OHNE
2197
+ * zusätzliche Größenklasse, projiziert über `<ng-content select="[cdsIcon]">`
2198
+ * (Kontrakt in der Story „Interaktiv“ per `getBoundingClientRect()` gepinnt).
2199
+ * Anders als `.ep-card-icon` (nur `background`, kein `color`) setzt
2200
+ * `.ep-feature-icon` UND ihre vier `[data-area]`-Varianten (css/components.css:
2201
+ * 1367–1372) zusätzlich `color` auf dem Container selbst. Das Mockup nutzt das
2202
+ * aktiv aus: die projizierten SVGs dort (`docs/index.html:10406` u. a.) tragen
2203
+ * `stroke="currentColor"` statt eines hart codierten Bereichstons — die Farbe
2204
+ * kommt allein aus dem Container, ein Icon-Autor muss den Bereich der Kachel gar
2205
+ * nicht kennen. Bei `cds-icon-card` ist das nicht möglich (kein `color` am
2206
+ * Container), dort trägt jedes Icon seinen Bereichston selbst im `stroke`-Attribut.
2207
+ * Story „Interaktiv“ demonstriert das mit `stroke="currentColor"` und prüft die
2208
+ * geerbte Farbe per `getComputedStyle()`. Die Icon-Kachel selbst ist im Mockup
2209
+ * (`docs/index.html:4883` u. a.) ein `<span aria-hidden="true">`, kein `<div>` —
2210
+ * rein dekorativ, das SVG trägt bereits sein eigenes `aria-hidden`; die Komponente
2211
+ * übernimmt beides unverändert.
2212
+ *
2213
+ * **CTA: `<a>` mit `href`, sonst `<span>` — nie ein `<a>` ohne `href`.**
2214
+ * css/components.css:1376 zielt mit `.ep-feature-body>.card-cta-link` auf den
2215
+ * direkten Nachfahren; Angulars `@if`/`@else` fügt dafür kein Wrapper-Element ein
2216
+ * (kompiliert zu Kommentar-Ankern, kein Element), der Kindselektor bleibt also in
2217
+ * beiden Zweigen erhalten. Ausgezählt in `docs/index.html`: alle 13 Vorkommen von
2218
+ * `.card-cta-link` innerhalb von `.ep-feature-body` sind entweder ein `<a
2219
+ * href="…">` (12×) oder ein `<span>` (1×, `docs/index.html:13216`,
2220
+ * „Landingpage folgt“ — Platzhalter für ein Ziel, das noch fehlt). Ein `<a>` OHNE
2221
+ * `href` kommt kein einziges Mal vor — dieselbe Falle, die `cds-icon-card` über
2222
+ * `isLink()` schließt (ein Link-Tag ohne `href` ist weder fokussierbar noch hat
2223
+ * es eine Link-Rolle, sieht mit der `.card-cta-link`-Optik aber trotzdem wie ein
2224
+ * bedienbares Element aus). Hier entscheidet sich das nicht am Host-Tag (der ist
2225
+ * bei `cdsFeature` immer `<div>`), sondern strukturell im eigenen Template:
2226
+ * `ctaHref` gesetzt → `<a class="card-cta-link" [href]="ctaHref()">`, leer →
2227
+ * `<span class="card-cta-link">` mit identischer Optik und identischem Pfeil,
2228
+ * aber ohne Link-Rolle (siehe Story „Ohne Href“). Ein `[attr.href]`-Nullwert wäre
2229
+ * dieselbe Krücke gewesen wie ein `<a>` ohne `href` zu tolerieren; der
2230
+ * `@if`/`@else`-Zweig macht den Fall stattdessen unmöglich, statt ihn nur
2231
+ * abzufedern. `data-area` sitzt auf beiden Zweigen, weil `.card-cta-link[data-area]`
2232
+ * (css/components.css:1363–1366) ein direkter Attributselektor ist, keine
2233
+ * Nachfahren-Regel wie `.ep-card[data-area] .ep-card-cta` bei der Icon-Karte —
2234
+ * ohne eigenes `data-area` bliebe der Link/Span auf der CSS-Vorgabefarbe, auch bei
2235
+ * gesetztem `area`.
2236
+ *
2237
+ * **`ctaAriaLabel` — der zugängliche Name ist im Mockup die Regel, nicht die
2238
+ * Ausnahme.** Erster Anlauf dieser Komponente hatte keinen solchen Input, mit der
2239
+ * (falschen) Annahme, das Mockup verzichte meist auf einen zusätzlichen
2240
+ * `aria-label`. Ausgezählt: von den 12 `<a class="card-cta-link">` in
2241
+ * `.ep-feature-body` tragen 11 einen `aria-label`, nur einer nicht
2242
+ * („Contentletter abonnieren“, `docs/index.html:15203` — der sichtbare Text ist
2243
+ * dort bereits eindeutig). Grund: nur 3 verschiedene sichtbare Texte verteilen
2244
+ * sich auf diese 12 Links, „Zur Landingpage“ allein zehnmal
2245
+ * (`docs/index.html:11587` u. a.) — eine Screenreader-Linkliste hörte sonst
2246
+ * zehnmal denselben Namen ohne Unterscheidung. Das Mockup disambiguiert
2247
+ * durchgängig mit der Form `<sichtbarer Text>: <Ziel>`
2248
+ * (`aria-label="Zur Landingpage: KI Kickstart Workshops"`). `ctaAriaLabel` ist
2249
+ * deshalb Beiwerk (Default `''`): leer bleibt der sichtbare `ctaLabel`-Text der
2250
+ * zugängliche Name (passt für einen eindeutigen CTA-Text wie „Contentletter
2251
+ * abonnieren“), gesetzt überschreibt er ihn — Konsumenten mit einer Liste
2252
+ * gleichlautender CTA-Texte (wie den zehn „Zur Landingpage“ im Mockup) setzen ihn
2253
+ * pro Instanz auf `<ctaLabel>: <Ziel>`. Wirkt nur am `<a>`-Zweig: `aria-label` an
2254
+ * einem `<span>` ohne Rolle hat keinen verlässlichen Effekt im
2255
+ * Accessibility-Baum, und der `<span>`-Zweig ist ohnehin nicht interaktiv.
2256
+ */
2257
+ declare class FeatureComponent {
2258
+ /** Titel (`.ep-feature-title`). */
2259
+ readonly title: _angular_core.InputSignal<string>;
2260
+ /** Beschreibungstext (`.ep-feature-text`). */
2261
+ readonly text: _angular_core.InputSignal<string>;
2262
+ /** Markenbereich → `data-area` auf Icon-Kachel und CTA-Link. */
2263
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
2264
+ /** CTA-Linktext (`.card-cta-link` als direktes Kind von `.ep-feature-body`, leer = kein CTA). */
2265
+ readonly ctaLabel: _angular_core.InputSignal<string>;
2266
+ /** CTA-Linkziel; gesetzt → `<a href>`, leer → `<span>` ohne Link-Rolle (siehe Klassendoku). */
2267
+ readonly ctaHref: _angular_core.InputSignal<string>;
2268
+ /**
2269
+ * Zugänglicher Name des CTA-Links, überschreibt den sichtbaren `ctaLabel`-Text.
2270
+ * Nötig, wenn derselbe sichtbare CTA-Text mehrfach auf einer Seite steht (siehe
2271
+ * Klassendoku); Form aus dem Mockup: `<ctaLabel>: <Ziel>`. Leer (Default) = kein
2272
+ * `aria-label`, der sichtbare `ctaLabel`-Text bleibt der zugängliche Name. Wirkt
2273
+ * nur, wenn `ctaHref` gesetzt ist (nur der `<a>`-Zweig hat eine Link-Rolle).
2274
+ */
2275
+ readonly ctaAriaLabel: _angular_core.InputSignal<string>;
2276
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FeatureComponent, never>;
2277
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FeatureComponent, "div[cdsFeature]", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "text": { "alias": "text"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "ctaLabel": { "alias": "ctaLabel"; "required": false; "isSignal": true; }; "ctaHref": { "alias": "ctaHref"; "required": false; "isSignal": true; }; "ctaAriaLabel": { "alias": "ctaAriaLabel"; "required": false; "isSignal": true; }; }, {}, never, ["[cdsIcon]"], true, never>;
2278
+ }
2279
+
2280
+ /**
2281
+ * CtaBand (`[cdsCtaBand]`) — Wrapper um `.ep-cta-band` aus css/components.css
2282
+ * (css/components.css:1456, Kopf-Duo `.ep-cta-h2`/`.ep-cta-sub` ebenda): das
2283
+ * bereichsgefärbte Page-End-CTA-Band, das laut Doku-Site (`docs/index.html:6237`,
2284
+ * Anker `gt-cta-band`) am Ende jeder Customer-Page direkt vor dem Footer steht — die
2285
+ * „letzte Einladung“, wenn die Nutzerin die Seite durchgelesen hat. Ausgezählt: 22
2286
+ * Vorkommen auf den Beispielseiten, ausnahmslos als `<div class="ep-cta-band"
2287
+ * style="background:…">` mit genau einer Aktion.
2288
+ *
2289
+ * **Entscheidung 1 — Attributselektor, kein eigenes Element (ADR-0008, derselbe
2290
+ * „Fläche am Host“-Fall wie `cds-section`).** `css/components.css` trägt für
2291
+ * `.ep-cta-band` KEIN `[data-area]` (per Grep geprüft, keine einzige Regel dieser
2292
+ * Form existiert). Die Bandfläche kommt in allen 22 Vorkommen als Inline-Style
2293
+ * DIREKT am `.ep-cta-band`-Element (`style="background:var(--co-700);color:#fff"`,
2294
+ * docs/index.html:6304 u. a.), dem Bereich der Page folgend, nie aus einem
2295
+ * `data-area`-Attribut. Ein Element-Selektor würde exakt den in ADR-0008 „Fall 2“
2296
+ * gemessenen Fehler wiederholen: der `<cds-cta-band>`-Host ist ein unbekanntes
2297
+ * Custom Element (`display:inline`), sein einziges Kind würde als Block
2298
+ * herausgebrochen, ein am Host gesetzter Inline-`background` hätte keine eigene Box
2299
+ * zum Malen. Die Komponente hängt sich deshalb als Attribut an ein vom Konsumenten
2300
+ * geschriebenes `<div>` (`<div cdsCtaBand style="background:…">`) — das Element, das
2301
+ * den Style trägt, und `.ep-cta-band` sind derselbe Knoten. Nur `<div>`, kein
2302
+ * `<section>`-Zwilling wie bei `cds-section`: alle 22 Vorkommen benutzen
2303
+ * ausnahmslos ein `<div>`, keines variiert das Tag.
2304
+ *
2305
+ * **Entscheidung 2 — `area` färbt nur die Aktion, nicht das Band.** Aus demselben
2306
+ * Grund wie bei `cds-section` (siehe dessen Klassendoku, Entscheidung 2) bleibt die
2307
+ * Bandfläche Sache des Konsumenten: welche Bereichsfarbe ein Band trägt, ist eine
2308
+ * Entscheidung der Seite (Bereichszugehörigkeit der Customer-Page), keine
2309
+ * Bauteil-Eigenschaft — und das CSS bietet an dieser Klasse ohnehin keinen
2310
+ * `[data-area]`-Haken an (siehe Entscheidung 1). `area` steuert deshalb
2311
+ * ausschließlich die Button-Farbklasse (`.btn-{area}`), nicht die Füllung des Bands.
2312
+ *
2313
+ * **Entscheidung 3 — `.btn-on-band` + `.btn-filled` direkt komponiert, nicht über
2314
+ * `cds-button` projiziert.** `cds-button` KENNT den Modifier
2315
+ * (`variant="filled-on-band"`, geprüft über `npx storybook tools docs show --id
2316
+ * komponenten-buttons-button` — die Story „Auf Bereichs-Band“ existiert dort
2317
+ * bereits). Trotzdem baut diese Komponente die `.btn`-Klassen direkt zusammen
2318
+ * (Präzedenzfall `download-cta.component.ts`), aus einem härteren Grund als dort:
2319
+ * `cds-button` rendert IMMER ein `<button>` — sein Input-Vertrag
2320
+ * (`ButtonComponentInputs`) kennt kein `href` — und kann die vom Ticket geforderte
2321
+ * Verzweigung „`primaryHref` gesetzt → `<a>`“ strukturell gar nicht erfüllen. Ein
2322
+ * projiziertes `<cds-button>` brächte hier also kein Custom-Element-Layoutproblem
2323
+ * (kein Kindselektor an `.ep-cta-band` hängt von der DOM-Tiefe ab), sondern schlicht
2324
+ * die falsche Fähigkeit.
2325
+ *
2326
+ * **Entscheidung 4 — bewusst nur EINE Aktion, kein `secondaryLabel`.** Eine frühere
2327
+ * Fassung bot `secondaryLabel`/`secondaryHref` an, ungeprüft gegen das Mockup. Beide
2328
+ * Belege dagegen: erstens zeigt KEINES der 22 `.ep-cta-band`-Vorkommen in
2329
+ * `docs/index.html` eine zweite Aktion — der Zwei-Aktionen-Fall hat keine Vorlage.
2330
+ * Zweitens (der schwerere Grund) lässt sich eine zweite, optisch zurückhaltendere
2331
+ * Aktion mit den vorhandenen Klassen gar nicht bauen: `.btn-{area}.btn-on-band{color:
2332
+ * …}` (css/components.css:47–51) überschreibt die Textfarbe JEDER Variante auf den
2333
+ * Bereichston — genau den Ton, den die Doku durchgängig als Bandhintergrund nennt.
2334
+ * Nur `.btn-filled` tauscht zusätzlich die Füllung gegen Weiß; `.btn-outlined`,
2335
+ * `.btn-tonal` und `.btn-text` blieben transparent und zeigten Text in derselben
2336
+ * Farbe wie das Band darunter — unsichtbar. Eine zweite Aktion hätte deshalb
2337
+ * zwangsläufig dieselbe Optik wie die erste getragen, keine Hierarchie, nur zwei
2338
+ * gleich gewichtete Buttons. Das ist eine CSS-Lücke (kein kontrastsicherer
2339
+ * sekundärer On-Band-Stil), festgehalten in
2340
+ * `.scratch/angular-seitenbausteine/issues/16-css-luecke-zweite-aktion-auf-band.md`
2341
+ * — gemeldet, nicht in diesem Wrapper improvisiert. Solange sie besteht, trägt
2342
+ * `cds-cta-band` nur eine Aktion; ein Konsument mit echtem Bedarf für eine zweite
2343
+ * schreibt sie außerhalb der Komponente ins Band hinein (`<ng-content>` gibt es
2344
+ * hier bewusst nicht, um genau das nicht als unterstützten Pfad zu suggerieren).
2345
+ * Ohne zweite Aktion braucht es auch keinen eigenen Container: die einzelne Aktion
2346
+ * zentriert sich über das ererbte `.ep-cta-band{text-align:center}` von selbst,
2347
+ * genau wie in allen 22 Mockup-Vorkommen — ein zusätzliches Flex-Layout im Wrapper
2348
+ * hätte eine Darstellung erfunden, die die CSS-Schicht so nicht kennt (ADR-0001;
2349
+ * die einzige existierende Deklaration dieser Form ist `.ep-hero-ctas`,
2350
+ * css/components.css:1222, eine andere Klasse für einen anderen Bauteiltyp).
2351
+ *
2352
+ * **Kein `aria-label` auf der Aktion.** Anders als bei `cds-feature`
2353
+ * (`ctaAriaLabel`, 11 von 12 Vorkommen mit `aria-label`) zeigt keines der 22
2354
+ * Band-Vorkommen einen `aria-label` auf seiner Aktion — ausgezählt, nicht
2355
+ * geschätzt. Die sichtbaren Texte sind durchgängig konkrete Verben mit Ziel
2356
+ * („Termin buchen“, „Gespräch anfragen“, „Offene Stellen ansehen“ …) und stehen je
2357
+ * Seite nur einmal; anders als bei einer Karten-Liste braucht es hier keine
2358
+ * Disambiguierung. Kein entsprechender Input.
2359
+ */
2360
+ declare class CtaBandComponent {
2361
+ /** Headline (`.ep-cta-h2`) — das konkrete Angebot, keine Marketing-Floskel. */
2362
+ readonly heading: _angular_core.InputSignal<string>;
2363
+ /** Beschriftung der (einzigen) Aktion. */
2364
+ readonly primaryLabel: _angular_core.InputSignal<string>;
2365
+ /** Unterzeile (`.ep-cta-sub`, leer = keine Unterzeile). */
2366
+ readonly sub: _angular_core.InputSignal<string>;
2367
+ /** Markenbereich → `.btn-{area}` auf der Aktion (nicht die Bandfläche, siehe Klassendoku). */
2368
+ readonly area: _angular_core.InputSignal<CdsArea>;
2369
+ /** Ziel der Aktion; gesetzt → `<a href>`, leer → `<button>` mit `primaryClick`. */
2370
+ readonly primaryHref: _angular_core.InputSignal<string>;
2371
+ /** Klick auf die Aktion (feuert nur, wenn `primaryHref` leer ist). */
2372
+ readonly primaryClick: _angular_core.OutputEmitterRef<MouseEvent>;
2373
+ /** @internal */
2374
+ protected readonly actionClasses: _angular_core.Signal<string>;
2375
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CtaBandComponent, never>;
2376
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CtaBandComponent, "div[cdsCtaBand]", never, { "heading": { "alias": "heading"; "required": true; "isSignal": true; }; "primaryLabel": { "alias": "primaryLabel"; "required": true; "isSignal": true; }; "sub": { "alias": "sub"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "primaryHref": { "alias": "primaryHref"; "required": false; "isSignal": true; }; }, { "primaryClick": "primaryClick"; }, never, never, true, never>;
2377
+ }
2378
+
2379
+ /**
2380
+ * Tier (`cds-tier`) — Wrapper um `.ep-tier` aus css/components.css
2381
+ * (css/components.css:1381–1384): der Stufen-Trenner (Label + Haarlinie), der eine
2382
+ * Offene Feature-Liste in Pakete gliedert (z. B. „In jedem Paket enthalten“ /
2383
+ * „Zusätzlich mit Pro“, Doku-Sektion `docs/index.html:4880`, Beispielseiten
2384
+ * `docs/index.html:11855–11857`, `11883–11885`, `12576–12578`).
2385
+ *
2386
+ * **Element-Selektor, kein Attribut (ADR-0008-Standardfall).** Ausgezählt: alle 4
2387
+ * `.ep-tier`-Vorkommen in `docs/index.html` stehen als eigenständiger `<div>` VOR
2388
+ * einem `.layout-grid` oder einer Karten-Reihe, nie als deren Kind — keines trägt
2389
+ * eine `col-*`-Spaltenklasse, keines liegt in einem Grid/Flex, das seine Kinder
2390
+ * dehnt. Das Tag variiert ebenfalls nicht (immer `<div>`). Keines der drei
2391
+ * ADR-0008-Kriterien (Grid-/Flex-Kind, Ziel einer Layout-Klasse, wechselndes Tag)
2392
+ * trifft zu, der Element-Selektor bleibt deshalb der Standardfall. `.ep-tier{
2393
+ * display:flex}` sitzt direkt auf dem Host (`host: { class: 'ep-tier' }`), kein
2394
+ * inneres Wrapper-Element darunter — anders als bei `cds-section` (ADR-0008 Fall 2)
2395
+ * ist hier nichts von außen auf eine bestimmte DOM-Tiefe angewiesen: kein
2396
+ * Nachfahren-Selektor zielt auf `.ep-tier`, keine Fläche hängt am Host.
2397
+ *
2398
+ * **`area` ist auf `'ki'` typisiert, nicht auf `CdsArea`.** `css/components.css:1383`
2399
+ * kennt nur die eine Regel `.ep-tier-label[data-area="ki"]` (Dark-Override
2400
+ * `css/dark-mode.css:476`) — für `co`/`es`/`wo` existiert keine einzige
2401
+ * `[data-area]`-Regel auf `.ep-tier-label`, per Grep über `css/*.css` geprüft.
2402
+ * Ausgezählt in `docs/index.html`: von 4 `.ep-tier-label`-Vorkommen tragen 3
2403
+ * `data-area="ki"` (4880, 11884, 12577), eines trägt gar kein `data-area` (11856),
2404
+ * keines der Werte `co`/`es`/`wo` kommt vor. Ein `area`-Input vom Typ `CdsArea`
2405
+ * würde für drei von vier gültigen Werten ein `data-area`-Attribut schreiben, das
2406
+ * im CSS folgenlos bleibt — die Falle, die genau dann entsteht, wenn eine Eingabe
2407
+ * mehr verspricht, als die Stilschicht einlöst. Der Typ ist deshalb auf den einen
2408
+ * Wert eingeschränkt, den das CSS tatsächlich kennt; der Compiler verhindert damit
2409
+ * strukturell, dass jemand `co`/`es`/`wo` setzt und ein wirkungsloses Attribut
2410
+ * bekommt, statt es nur im JSDoc zu behaupten.
2411
+ */
2412
+ declare class TierComponent {
2413
+ /** Beschriftung des Trenners (`.ep-tier-label`), z. B. „In jedem Paket enthalten“. */
2414
+ readonly label: _angular_core.InputSignal<string>;
2415
+ /**
2416
+ * Einzige vom CSS unterstützte Tönung → `data-area="ki"` auf `.ep-tier-label`.
2417
+ * Ungesetzt (Default) bleibt das Label neutral (`--tx-secondary`), siehe Klassendoku.
2418
+ */
2419
+ readonly area: _angular_core.InputSignal<"ki" | undefined>;
2420
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TierComponent, never>;
2421
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TierComponent, "cds-tier", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2422
+ }
2423
+
2424
+ /** Ein Fakten-Paar der Angebots-Rahmendaten (`<dt>`/`<dd>`). */
2425
+ interface CdsFactsItem {
2426
+ /** Label (`<dt>`), z. B. „Dauer“. */
2427
+ term: string;
2428
+ /** Wert (`<dd>`), z. B. „2 Tage, 9–17 Uhr“. */
2429
+ value: string;
2430
+ }
2431
+ /**
2432
+ * Facts (`cds-facts`) — Wrapper um `.ep-facts` aus css/components.css
2433
+ * (css/components.css:1261–1272): die Definitionsliste für die harten Eckdaten
2434
+ * eines Angebots (Termin, Dauer, Ort, Preis), einspaltig mit Haarlinie zwischen
2435
+ * den Paaren oder als `.is-grid` zweispaltig für Kästen, die neben Inhalt stehen.
2436
+ * Bewusst ohne eigenen Rahmen und ohne Fläche, sie zieht in einen vorhandenen
2437
+ * Container ein (Angebots-Box, Sticky-Sidebar) — Doku-Sektion
2438
+ * `docs/index.html:9069` (`gt-seminar-fakten`), Beispielseiten `docs/index.html:
2439
+ * 9076–9082`, `13718–13726`, `16293–16300`.
2440
+ *
2441
+ * **Element-Selektor, kein Attribut (ADR-0008-Standardfall).** Ausgezählt: keines
2442
+ * der 3 `.ep-facts`-Vorkommen in `docs/index.html` sitzt in einem `.layout-grid`
2443
+ * mit `col-*`, keines wird von einem Grid-/Flex-Elternteil in der Höhe gedehnt
2444
+ * (der Flex-Fall in Zeile 16290 ist `flex-direction:column`, dort füllen Block-
2445
+ * Elemente die Breite ihres Containers unabhängig von einer zusätzlichen
2446
+ * Wrapper-Ebene — anders als bei `.ep-card`/ADR-0008 Fall 1 geht es dort um Höhe,
2447
+ * die durch Block-Layout NICHT automatisch nach unten durchgereicht wird). Das
2448
+ * Tag variiert nicht (immer `<dl>`). Analog zu `cds-faq` (`faq.component.ts`, das
2449
+ * intern `<details>` in einem `<div class="ep-faq">` rendert) trägt hier die
2450
+ * INNERE `<dl class="ep-facts">` die CSS-Klasse, nicht der `<cds-facts>`-Host: die
2451
+ * Semantik einer Definitionsliste hängt am `<dl>`-Tag selbst, ein Custom-Element
2452
+ * kann dieses Tag nicht annehmen. Da `.ep-facts > div + div` ausschließlich
2453
+ * Nachfahren INNERHALB der eigenen Vorlage anspricht, bricht eine zusätzliche
2454
+ * Host-Ebene darüber nichts — anders als bei `cds-section` (Fall 2) hängt hier
2455
+ * keine von außen gesetzte Fläche oder ein von außen adressierter Nachfahre an
2456
+ * dieser Tiefe.
2457
+ *
2458
+ * **`<dl>`/`<div>`/`<dt>`/`<dd>` exakt wie vom CSS erwartet.** `.ep-facts > div +
2459
+ * div` (css/components.css:1262) setzt Haarlinie und Abstand ab dem ZWEITEN Paar;
2460
+ * ohne das umschließende `<div>` pro Paar griffe der Selektor nicht. Jedes
2461
+ * `items()`-Element wird deshalb zu genau einem `<div><dt>…</dt><dd>…</dd></div>`.
2462
+ *
2463
+ * **`area` färbt `<dt>` über `.t-{area}`, nicht über `data-area`.** Anders als bei
2464
+ * `cds-feature`/`cds-icon-card` kennt `.ep-facts` selbst kein `[data-area]`; der
2465
+ * CSS-Kommentar zu dieser Klasse (`css/components.css:1259`) benennt
2466
+ * stattdessen ausdrücklich „Bereichston der Labels über `.t-XX` im Markup
2467
+ * (dark-safe), nie als Inline-Farbe“ als sanktionierten Weg. Ausgezählt: alle 3
2468
+ * `.ep-facts`-Vorkommen in `docs/index.html` setzen `.t-wo` auf JEDEM `<dt>`
2469
+ * derselben Liste (nie gemischt, nie eine andere Bereichsfarbe) — ein optionaler
2470
+ * `area`-Input, der `.t-{area}` einheitlich auf alle `<dt>` der Instanz anwendet,
2471
+ * bildet dieses Muster nach, ohne einen Farbwert zu erfinden (`.t-XX` ist eine
2472
+ * bestehende, bereits kontrast- und dark-mode-geprüfte Utility, `css/components.css
2473
+ * :638–642`). Ungesetzt (Default) bleibt `<dt>` ohne zusätzliche Klasse, erbt also
2474
+ * die umgebende Textfarbe — das deckt Kontexte ohne Bereichsbindung ab.
2475
+ *
2476
+ * **Über die Ticket-API hinaus:** `area` stand nicht in der ursprünglichen
2477
+ * API-Skizze von Ticket 08. Ergänzt, weil ohne ihn KEINES der 3 realen
2478
+ * `.ep-facts`-Vorkommen originalgetreu nachgebaut werden könnte — anders als bei
2479
+ * `cds-tier`s `area` (dort deckt die Einschränkung eine tatsächliche CSS-Lücke
2480
+ * ab) fehlt hier keine CSS-Regel, nur ein API-Hook auf eine bereits vollständige
2481
+ * Klasse. Siehe Ticket-Bericht für die Abwägung.
2482
+ */
2483
+ declare class FactsComponent {
2484
+ /** Fakten-Paare (`<dt>`/`<dd>`), in Darstellungsreihenfolge. */
2485
+ readonly items: _angular_core.InputSignal<CdsFactsItem[]>;
2486
+ /** Zweispaltige Rasterung ohne Haarlinien (`.is-grid`) statt der einspaltigen Grundform. */
2487
+ readonly grid: _angular_core.InputSignal<boolean>;
2488
+ /** Markenbereich → `.t-{area}` auf jedem `<dt>` (siehe Klassendoku). Ungesetzt = neutral. */
2489
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
2490
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FactsComponent, never>;
2491
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FactsComponent, "cds-facts", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "grid": { "alias": "grid"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2492
+ }
2493
+
2494
+ /**
2495
+ * Table (`cds-table`) — Wrapper um `.tbl`/`.tbl-wrap` aus css/components.css
2496
+ * (css/components.css:1462–1480): die Datentabelle der Doku-Site (`sec-table`,
2497
+ * Nav-Einträge „Standard“ und „Gestreift“). Ausgezählt: außerhalb von `sec-table`
2498
+ * selbst kommt `.tbl-wrap` nur zweimal vor, beide auf Beitragsseiten
2499
+ * (`docs/index.html:8622`, `15080`) — keine der 24 Beispielseiten außerhalb von
2500
+ * Wissensbeiträgen setzt aktuell eine Tabelle ein. Neuntes Ticket der
2501
+ * Seitenbausteine-Serie.
2502
+ *
2503
+ * **Kein Daten-Input.** Eine `columns`/`rows`-API würde Zellinhalte auf Strings
2504
+ * festlegen; die Beispielseiten setzen darin Badges, Links und `data-num`
2505
+ * (`docs/index.html:5076–5177`). Der Konsument projiziert `<thead>`/`<tbody>`/
2506
+ * `<tfoot>` unverändert per `<ng-content>`, die Komponente liefert nur die
2507
+ * Hülle: `.tbl-wrap`, `.tbl`, `<caption>` und die Striped-Klasse.
2508
+ *
2509
+ * **`caption` ist Pflicht (`input.required<string>()`), abweichend von der
2510
+ * Ticket-Skizze (dort `caption? = ''`).** Die eigene Doku dieser Komponente
2511
+ * (`storybook-angular/src/docs/komponenten/tabelle.mdx:137`) nennt `<caption>`
2512
+ * ausdrücklich „Pflicht, Screenreader lesen den Titel vor, bevor die Zellen
2513
+ * vorgelesen werden“ und wiederholt das in den Dos (`tabelle.mdx:147`:
2514
+ * „`<caption>` und `scope`-Attribute immer setzen, auch bei einfachen
2515
+ * Tabellen“). Ausgezählt: alle 5 realen `.tbl`-Vorkommen in `docs/index.html`
2516
+ * haben eine `<caption>`, ausnahmslos. Ein optionaler Input mit Default `''`
2517
+ * hätte genau den Fall erlaubt, den die eigene Doku verbietet — nach
2518
+ * ADR-0007 §2 ist `caption` damit Inhalt, nicht Beiwerk: ohne sie ist eine
2519
+ * `cds-table` eine Tabelle, die die eigenen Barrierefreiheitsregeln bricht,
2520
+ * also sinnlos. Ein vergessenes Binding wirft jetzt `NG0950`, statt eine
2521
+ * unbeschriftete Tabelle still auszuliefern.
2522
+ *
2523
+ * **Element-Selektor, `.tbl-wrap`/`.tbl` sitzen im eigenen Template, nicht am
2524
+ * Host (ADR-0008-Standardfall, analog zu `cds-facts`/`cds-faq`).** Ausgezählt:
2525
+ * alle 5 `.tbl-wrap`-Vorkommen in `docs/index.html` (Zeilen 5061, 5116, 5236,
2526
+ * 8622, 15080). Keines ist selbst ein direktes Grid-/Flex-Kind — das einzige
2527
+ * Vorkommen in einem `.layout-grid` (Zeile 5236) sitzt eine Ebene tiefer in
2528
+ * einem `.col-8`, das seinerseits der Grid-Child ist; `.tbl-wrap` ist dort ein
2529
+ * gewöhnlicher Block-Nachfahre, dessen Breite vom umschließenden `.col-8`
2530
+ * kommt, nicht von `align-items:stretch` auf einer bestimmten DOM-Tiefe (kein
2531
+ * `.ep-card`-Fall). Keines trägt eine `col-*`-Klasse selbst, keines variiert
2532
+ * das Tag (immer `<div class="tbl-wrap">`). Ein `<cds-table>`-Host ohne eigene
2533
+ * Klasse und ohne eigenes `background` gerät deshalb nicht in den „Fläche am
2534
+ * Host“-Fall aus ADR-0008 Fall 2: die Komponente setzt nichts auf dem Host,
2535
+ * das eine eigene Box bräuchte, `.tbl-wrap` bleibt ein normaler Block-Nachfahre
2536
+ * unabhängig vom `display` des `<cds-table>`-Hosts (derselbe Grund, warum
2537
+ * `cds-facts`/`cds-faq` als Element-Selektor funktionieren).
2538
+ *
2539
+ * Eine Attributselektor-Variante direkt am `<table>` (`table[cdsTable]`, analog
2540
+ * zu `cdsSection`) wurde erwogen und verworfen: `<table>` ist als Tag ohnehin
2541
+ * fix (kein Tag-Wechsel wie bei `cdsIconCard`), aber `.tbl-wrap` bräuchte dann
2542
+ * ein ZWEITES Element, das der Konsument von Hand um die Tabelle schreiben
2543
+ * müsste (`<div class="tbl-wrap" tabindex="0" role="region" aria-label="…">
2544
+ * <table cdsTable>…`) — genau die beiden Aufgaben, die laut Ticket am ehesten
2545
+ * vergessen werden (fokussierbarer, benannter Scroll-Container), blieben dann
2546
+ * beim Konsumenten statt bei der Komponente. Der Element-Selektor hält Wrap und
2547
+ * Tabelle zusammen in einem Template.
2548
+ *
2549
+ * **Geprüft im laufenden Storybook (Story „Interaktiv“, Play-Funktion):**
2550
+ * `<table class="tbl">` liegt direkt unter `<div class="tbl-wrap">`, `<caption>`
2551
+ * ist ihr erstes Kind, danach folgen ohne zusätzlichen Knoten dazwischen genau
2552
+ * die projizierten `<thead>`/`<tbody>`-Elemente — `<ng-content>` fügt selbst
2553
+ * kein DOM-Element ein, es verschiebt nur die vom Konsumenten geschriebenen
2554
+ * nativen Elemente an ihre Stelle. Damit bleibt die Tabellenstruktur (`<table>`
2555
+ * → `<caption>` + `<thead>` + `<tbody>` + optional `<tfoot>`, keine fremde
2556
+ * Ebene dazwischen) exakt so gültig wie im rohen Markup.
2557
+ *
2558
+ * **`.tbl-wrap` ist immer fokussierbar UND immer benannt.** Das CSS gibt dem
2559
+ * Scroll-Container einen eigenen `:focus-visible`-Ring
2560
+ * (css/components.css:1463) — ein scrollbarer Bereich muss per Tastatur
2561
+ * erreichbar sein (WCAG 2.1.1), `tabindex="0"` steht deshalb fest im Template.
2562
+ * `role="region"` braucht laut HTML-AAM einen zugänglichen Namen, sonst bekäme
2563
+ * der Bereich keine Landmark-Rolle — weil `caption` jetzt Pflicht ist, kann
2564
+ * `accessibleName()` (`scrollLabel() || caption()`) nicht mehr leer werden,
2565
+ * `role`/`aria-label` sind deshalb unbedingt gesetzt, kein Nullfall mehr zu
2566
+ * behandeln. `scrollLabel` bleibt eine optionale Überschreibung (Vorrang vor
2567
+ * `caption`) für Fälle, in denen der sichtbare Tabellentitel für den
2568
+ * Scroll-Container zu lang oder zu unspezifisch wäre.
2569
+ *
2570
+ * **`.tbl-sort` bleibt außen vor.** Die Klasse existiert
2571
+ * (css/components.css:1477–1482), die Sortierlogik nicht — kein zugehöriges
2572
+ * JS in `docs/main.js` für die Beispielseiten. Ein Wrapper, der nur den
2573
+ * Button-Look lieferte, täuschte Funktion vor, die es nicht gibt. Siehe
2574
+ * `.scratch/angular-seitenbausteine/issues/19-fehlende-sortierlogik-tbl-sort.md`.
2575
+ */
2576
+ declare class TableComponent {
2577
+ /** Überschrift der Tabelle (`<caption>`, erstes Kind) — Pflicht, siehe Klassendoku. */
2578
+ readonly caption: _angular_core.InputSignal<string>;
2579
+ /** Alternierende Zeilenfarbe für Tabellen mit vielen Zeilen (`.tbl--striped`). */
2580
+ readonly striped: _angular_core.InputSignal<boolean>;
2581
+ /**
2582
+ * Zugänglicher Name des Scroll-Containers (`aria-label` auf `.tbl-wrap`), hat
2583
+ * Vorrang vor `caption`. Leer = `caption` wird zum Namen (siehe Klassendoku).
2584
+ */
2585
+ readonly scrollLabel: _angular_core.InputSignal<string>;
2586
+ /**
2587
+ * Name des Scroll-Containers: `scrollLabel` hat Vorrang, sonst `caption` —
2588
+ * dank Pflicht-`caption` nie leer (siehe Klassendoku).
2589
+ *
2590
+ * @internal
2591
+ */
2592
+ protected readonly accessibleName: _angular_core.Signal<string>;
2593
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableComponent, never>;
2594
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableComponent, "cds-table", never, { "caption": { "alias": "caption"; "required": true; "isSignal": true; }; "striped": { "alias": "striped"; "required": false; "isSignal": true; }; "scrollLabel": { "alias": "scrollLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2595
+ }
2596
+
2597
+ /** Eine Vergleichsspalte (Paket/Tarif) der Vergleichstabelle. */
2598
+ interface CdsCompareColumn {
2599
+ /** Spaltenüberschrift, z. B. „Core“ oder „Pro“. */
2600
+ label: string;
2601
+ /** Hervorgehobene Spalte (`.ep-compare-pro`), z. B. das empfohlene Paket. */
2602
+ pro?: boolean;
2603
+ }
2604
+ /** Eine Vergleichszeile: das verglichene Merkmal plus eine Zelle je Spalte. */
2605
+ interface CdsCompareRow {
2606
+ /** Zeilenüberschrift (`<th scope="row">`), das verglichene Merkmal. */
2607
+ label: string;
2608
+ /**
2609
+ * Eine Zelle je Eintrag in `columns`, in derselben Reihenfolge. `boolean` → Ja/Nein-Glyphe
2610
+ * (`.ep-compare-yes`/`-no`) mit Screenreader-Text, `string` → die kurze Angabe als Text
2611
+ * (z. B. „bis 70 Mrd. Param.“).
2612
+ */
2613
+ cells: (boolean | string)[];
2614
+ }
2615
+ /**
2616
+ * Compare (`cds-compare`) — Wrapper um `.ep-compare*` aus css/components.css
2617
+ * (css/components.css:1275–1294): die aufklappbare Vergleichstabelle für den zeilenweisen
2618
+ * Direktvergleich mehrerer Pakete/Tarife (Doku-Site `sec-table`, Nav-Eintrag
2619
+ * „Vergleichstabelle (aufklappbar)“, `docs/index.html:5182–5204`). Zehntes Ticket der
2620
+ * Seitenbausteine-Serie, nach `cds-table` (Ticket 09).
2621
+ *
2622
+ * **Mit Daten-Input, anders als `cds-table`.** `cds-table` projiziert `<thead>`/`<tbody>`
2623
+ * unverändert per `<ng-content>`, weil seine Zellen Badges, Links und `data-num` tragen können
2624
+ * (siehe dessen Klassendoku). Hier ist der Zellinhalt strukturell auf Ja/Nein oder eine kurze
2625
+ * Angabe begrenzt — ausgezählt: alle 22 Datenzellen des einzigen realen Vorkommens
2626
+ * (`docs/index.html:11970–12038`, 11 Zeilen × 2 Spalten, ohne die Zeilenüberschriften) sind
2627
+ * entweder ein `.ep-compare-yes`/`-no`-Marker (18×, davon 14× „Ja“, 4× „Nein“) oder ein kurzer
2628
+ * Text wie „bis 70 Mrd. Param.“ bzw. „30 Min.“ (4×) — nie ein Badge, Link oder anderes Markup.
2629
+ * Weil Spaltenzahl, `pro`-Spalte und Zellinhalt damit vollständig aus zwei Arrays (`columns`,
2630
+ * `rows`) hervorgehen, würde `<ng-content>` beim Konsumenten nur denselben `@for`-Code
2631
+ * duplizieren, ohne eine Freiheit zu gewinnen, die die Zell-Typisierung (`boolean | string`)
2632
+ * ohnehin ausschließt.
2633
+ *
2634
+ * **Ja/Nein-Zellen tragen einen Screenreader-Text, übernommen statt erfunden.** Im einzigen
2635
+ * realen Vorkommen steht hinter jeder Glyphe ein `.sr-only`-Text, ausnahmslos:
2636
+ * `<span class="ep-compare-yes" aria-hidden="true">✓</span><span class="sr-only">Enthalten</span>`
2637
+ * (14×) bzw. `<span class="ep-compare-no" aria-hidden="true">−</span><span class="sr-only">Nicht
2638
+ * enthalten</span>` (4×, „−“ ist U+2212 Minus, kein Bindestrich). Genau diese Zeichen und dieser
2639
+ * Wortlaut, keine eigene Formulierung — Farbe und Glyphe allein tragen keine Bedeutung
2640
+ * (WCAG 1.4.1), der `.sr-only`-Text ist deshalb kein optionaler Zusatz, sondern fest verdrahtet,
2641
+ * nicht per Input überschreibbar.
2642
+ *
2643
+ * **`caption` ist Pflicht (`input.required<string>()`), abweichend von der Ticket-Skizze (dort
2644
+ * kein Input dafür vorgesehen) — dieselbe Begründung wie bei `cds-table`.** Die eigene Doku
2645
+ * (`storybook-angular/src/docs/komponenten/tabelle.mdx:91`) nennt `<caption class="sr-only">`
2646
+ * ausdrücklich als Teil des Bauteils, und das einzige reale Vorkommen hat eine. Anders als bei
2647
+ * `cds-table` ist sie hier `.sr-only`, nicht sichtbar: der Klartext steht schon im `<summary>`
2648
+ * (`summary`-Input), die `<caption>` wiederholt ihn nur für Screenreader, die nach dem Aufklappen
2649
+ * direkt in die Tabelle springen, ohne den Summary-Text erneut vorgelesen zu bekommen.
2650
+ *
2651
+ * **`rowsLabel` (erste Kopfzelle, `<th scope="col">Funktion</th>` im Mockup) ist dagegen Beiwerk,
2652
+ * optional mit Default `''`.** Auch dafür sieht die Ticket-Skizze keinen Input vor. Den Text fest
2653
+ * im Template zu verdrahten hieße, AI.Box-Copy in einen wiederverwendbaren Wrapper zu backen
2654
+ * (ADR-0007 §2); ihn ganz wegzulassen wich ohne CSS-Befund vom einzigen Beleg ab, ohne dass die
2655
+ * Doku das verlangt. Anders als `caption` ist die Kopfzelle nicht barrierefreiheitsrelevant
2656
+ * Pflicht: ein leeres `<th scope="col">` bleibt eine gültige, in Vergleichsmatrizen verbreitete
2657
+ * Ecke ohne eigenen Namen. Deshalb Beiwerk, kein Inhalt — das Beispielwort „Funktion“ steht in
2658
+ * der Story, nicht in der Klasse.
2659
+ *
2660
+ * **Natives `<details>`/`<summary>` bleibt erhalten, kein nachgebautes Disclosure** (Ticket-
2661
+ * Vorgabe, analog `cds-faq`): Tastaturbedienung und Toggle-Verhalten kommen vom Browser, das CSS
2662
+ * hängt direkt an `[open]` (`.ep-compare[open] .ep-compare-caret`). `<details class="ep-compare">`
2663
+ * sitzt deshalb im TEMPLATE, nicht am Host — derselbe Grund wie bei `cds-table`s
2664
+ * `.tbl-wrap`/`.tbl`: ein `<cds-compare>`-Host ist ein unbekanntes Custom Element, kein echtes
2665
+ * `<details>`, und kann dessen native Disclosure-Semantik nicht annehmen.
2666
+ *
2667
+ * **Element-Selektor (ADR-0008-Standardfall).** `.ep-compare` sitzt im einzigen realen Vorkommen
2668
+ * als gewöhnlicher Block-Nachfahre in `.ep-section` (`docs/index.html:11969`) — kein Grid-/
2669
+ * Flex-Kind, keine `col-*`-Klasse vom Konsumenten, kein Tag-Wechsel (immer `<details>`). Keines
2670
+ * der drei ADR-0008-Kriterien greift, ein Attributselektor brächte hier nichts.
2671
+ *
2672
+ * **`open` ist ein reiner Anfangszustand, keine Zwei-Wege-Bindung.** Gebunden über
2673
+ * `[attr.open]="open() ? '' : null"`: Angular schreibt das Attribut nur, wenn sich der GEPRÜFTE
2674
+ * Ausdruckswert seit dem letzten Change-Detection-Lauf ändert. `open()` bleibt nach dem ersten
2675
+ * Rendern konstant (die Komponente schreibt nie in dieses Signal zurück), ein nachfolgender
2676
+ * nativer Toggle wird deshalb nicht rückgängig gemacht — geprüft in der Story „Interaktiv“
2677
+ * (Play-Funktion: Klick öffnet, `toggled` feuert `true`, ein zweiter, vom Toggle unabhängiger
2678
+ * Interaktionsschritt lässt die Tabelle weiterhin offen).
2679
+ */
2680
+ declare class CompareComponent {
2681
+ /** Text im `<summary>`, z. B. „Alle Funktionen vergleichen“. */
2682
+ readonly summary: _angular_core.InputSignal<string>;
2683
+ /** `<caption class="sr-only">` der Tabelle — Pflicht, siehe Klassendoku. */
2684
+ readonly caption: _angular_core.InputSignal<string>;
2685
+ /** Überschrift der ersten Spalte (Zeilentitel, z. B. „Funktion“) — Beiwerk, siehe Klassendoku. */
2686
+ readonly rowsLabel: _angular_core.InputSignal<string>;
2687
+ /** Anfangszustand des `<details>` — reine Vorbelegung, siehe Klassendoku. */
2688
+ readonly open: _angular_core.InputSignal<boolean>;
2689
+ /** Vergleichsspalten (Pakete/Tarife), in Render-Reihenfolge. */
2690
+ readonly columns: _angular_core.InputSignal<CdsCompareColumn[]>;
2691
+ /** Vergleichszeilen; `cells` hat je Zeile genau einen Eintrag pro Spalte in `columns`. */
2692
+ readonly rows: _angular_core.InputSignal<CdsCompareRow[]>;
2693
+ /** Feuert bei jedem Auf- oder Zuklappen mit dem neuen Zustand. */
2694
+ readonly toggled: _angular_core.OutputEmitterRef<boolean>;
2695
+ /** @internal */
2696
+ protected onToggle(event: Event): void;
2697
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CompareComponent, never>;
2698
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CompareComponent, "cds-compare", never, { "summary": { "alias": "summary"; "required": true; "isSignal": true; }; "caption": { "alias": "caption"; "required": true; "isSignal": true; }; "rowsLabel": { "alias": "rowsLabel"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rows": { "alias": "rows"; "required": true; "isSignal": true; }; }, { "toggled": "toggled"; }, never, never, true, never>;
2699
+ }
2700
+
2701
+ /** Größenvarianten von `cds-avatar` (`.article-avatar` / `-lg` / `-xl`). */
2702
+ type CdsAvatarSize = 'sm' | 'lg' | 'xl';
2703
+ /**
2704
+ * Avatar (`div[cdsAvatar]`) — Wrapper um `.article-avatar` aus css/components.css
2705
+ * (css/components.css:1520–1536): der Initialen-/Foto-Kreis im Meta-Strip eines
2706
+ * Wissensbeitrags (`.article-meta-author`), in der Author-Card (`-lg`) und im
2707
+ * Team-Tile-Grid (`-xl`). Elftes Ticket der Seitenbausteine-Serie.
2708
+ *
2709
+ * **Attributselektor (ADR-0008), gemessen an der Geschwister-Kette.** Ausgezählt in
2710
+ * `docs/index.html`: 8 der 11 Instanzen der Grundgröße sitzen als direkte, adjazente
2711
+ * Geschwister in einer von 3 `.article-avatar-stack`-Kacheln (2 Avatare in Zeilen
2712
+ * 8343–8344, je 3 in Zeilen 8373–8375 und 8404–8406) — genau dort greift
2713
+ * `.article-avatar-stack .article-avatar + .article-avatar`
2714
+ * (css/components.css:1540–1541), eine Geschwister-Kette (Kriterium `spec.md` 2b).
2715
+ * Ein Element-Selektor `cds-avatar`, der `.article-avatar` auf einem INNEREN Element
2716
+ * rendert (wie `cds-facts` es mit `<dl>` tut, weil `<dl>` ein Custom Element nicht
2717
+ * annehmen kann), würde diese Kette brechen: die beiden `.article-avatar`-Knoten
2718
+ * lägen dann je eine Ebene UNTER ihrem eigenen `<cds-avatar>`-Host und wären keine
2719
+ * Geschwister mehr — `+` verlangt denselben Elternknoten, egal wie dicht die Hosts
2720
+ * selbst nebeneinanderstehen. Eine zweite, ebenfalls tragfähige Variante
2721
+ * (Element-Selektor MIT `host: { class: 'article-avatar' }`, ohne innere
2722
+ * Wrapper-Ebene) hätte dieselbe Geschwister-Kette ebenso erfüllt — verworfen zugunsten
2723
+ * des Attributselektors nur wegen des zweiten, unabhängigen Grundes unten, nicht weil
2724
+ * sie die Kette nicht gelöst hätte.
2725
+ *
2726
+ * **Gemessen, nicht nur hergeleitet.** Story „Avatar-Stapel“ (Play-Funktion) rendert
2727
+ * drei `div[cdsAvatar]` in einem `cds-avatar-stack` und misst
2728
+ * `getBoundingClientRect()` der drei `.article-avatar`-Knoten: bei 40 px Kachelbreite
2729
+ * und `margin-left:-12px` (css/components.css:1541) überlappen der zweite und dritte
2730
+ * Kreis den jeweils vorherigen um 12 px (Differenz der `left`-Koordinaten = 28 px,
2731
+ * nicht 40 px) — plus Screenshot-Baseline (`visual-snapshots/…avatar-stapel.png`) als
2732
+ * visuelle Bestätigung, nicht nur die Zahl.
2733
+ *
2734
+ * **Zweiter, unabhängiger Grund: Wiederverwendung als Projektions-Selektor.**
2735
+ * `cds-article-header` projiziert den Avatar über
2736
+ * `<ng-content select="[cdsAvatar]">` (siehe dessen Klassendoku) — dasselbe Attribut,
2737
+ * das hier den Host selektiert, dient dem Elternteil zugleich als
2738
+ * Content-Projection-Selektor. Ein Element-Selektor bräuchte dafür eine zusätzliche,
2739
+ * eigens erfundene Marker-Klasse; der Attributselektor liefert die Zielscheibe für
2740
+ * beide Zwecke aus einer Hand, ohne dass der Konsument zwei Attribute schreiben muss.
2741
+ *
2742
+ * **Initialen werden aus `name` abgeleitet, kein eigener Input** (Ticket-Vorgabe):
2743
+ * erstes Zeichen des ersten und des letzten durch Whitespace getrennten Worts, groß
2744
+ * — ein einzelnes Wort liefert dessen erste zwei Zeichen. Zwei Inputs für dieselbe
2745
+ * Information (Name UND Initialen) könnten auseinanderlaufen, sobald nur eines
2746
+ * gepflegt wird.
2747
+ *
2748
+ * **`aria-hidden="true"` fest verdrahtet, kein Input.** Ausgezählt: von 53
2749
+ * `.article-avatar`-Instanzen (11 Grundgröße + 17 `-lg` + 25 `-xl`) tragen 45 das
2750
+ * Attribut direkt am Element; die restlichen 8 sind genau die Grundgrößen-Avatare
2751
+ * INNERHALB von `.article-avatar-stack`, wo bereits der Stack-Container selbst
2752
+ * `aria-hidden="true"` trägt (siehe `AvatarStackComponent`) — dort wäre ein zweites
2753
+ * `aria-hidden` am Kind redundant, aber unschädlich: verschachteltes `aria-hidden`
2754
+ * ändert nichts am Ergebnis, der Teilbaum ist so oder so für Assistenztechnologie
2755
+ * unsichtbar. Der Avatar trägt es deshalb immer: 100 % Deckung mit dem Mockup im
2756
+ * Alleinstand, harmlose Redundanz im Stapel.
2757
+ */
2758
+ declare class AvatarComponent {
2759
+ /** Voller Name — Quelle der Initialen und des Bild-`alt`-Texts. */
2760
+ readonly name: _angular_core.InputSignal<string>;
2761
+ /** Größe (`.article-avatar` = sm, `-lg`, `-xl`). */
2762
+ readonly size: _angular_core.InputSignal<CdsAvatarSize>;
2763
+ /** Markenbereich → `data-area` (Füllfarbe der Initialen-Kachel). */
2764
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
2765
+ /** Bildquelle; gesetzt → `<img>` ersetzt die Initialen. */
2766
+ readonly src: _angular_core.InputSignal<string>;
2767
+ /**
2768
+ * Erstes Zeichen des ersten und letzten Worts aus `name`, groß — bei einem
2769
+ * einzelnen Wort dessen erste zwei Zeichen.
2770
+ *
2771
+ * @internal
2772
+ */
2773
+ protected readonly initials: _angular_core.Signal<string>;
2774
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AvatarComponent, never>;
2775
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AvatarComponent, "div[cdsAvatar]", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "src": { "alias": "src"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2776
+ }
2777
+
2778
+ /**
2779
+ * AvatarStack (`cds-avatar-stack`) — Wrapper um `.article-avatar-stack` aus
2780
+ * css/components.css (css/components.css:1538–1545): mehrere `div[cdsAvatar]`
2781
+ * überlappend für Mehrfach-Autor:innen im Meta-Strip, mit optionalem
2782
+ * „+N“-Indikator (`.article-avatar-more`) ab vier Personen (siehe
2783
+ * `wissensbeitrag.mdx`, Abschnitt „Mehrere Autor:innen“).
2784
+ *
2785
+ * **Element-Selektor, ADR-0008-Standardfall.** `.article-avatar-stack` ist selbst
2786
+ * nie Grid-/Flex-Kind mit Stretch-Bedarf — sein einziger reale Elternkontext,
2787
+ * `.article-meta-author`, ist `display:flex;align-items:center` (center, nicht
2788
+ * stretch, css/components.css:1514), variiert nicht das Tag und ist selbst nie Teil
2789
+ * einer `+`-Kette (nur SEINE Kinder sind das, siehe `AvatarComponent`). Die Klasse
2790
+ * darf deshalb direkt am `<cds-avatar-stack>`-Host sitzen.
2791
+ *
2792
+ * **`<ng-content>` fügt kein eigenes Element ein**, die projizierten
2793
+ * `div[cdsAvatar]` bleiben deshalb direkte, adjazente Geschwister des optionalen
2794
+ * `.article-avatar-more`-Kreises — Voraussetzung für
2795
+ * `.article-avatar-stack .article-avatar + .article-avatar-more`
2796
+ * (css/components.css:1541).
2797
+ *
2798
+ * **`aria-hidden="true"` fest verdrahtet.** Ausgezählt: alle 3 realen
2799
+ * `.article-avatar-stack`-Vorkommen (`docs/index.html:8342,8372,8403`) tragen es —
2800
+ * dieselbe Begründung wie in `wissensbeitrag.mdx` („Barrierefreiheit“): Namen stehen
2801
+ * vollständig als Text in `.article-meta-name`, der Stapel selbst trägt keine eigene
2802
+ * Information, der „+N“-Kreis ebenfalls nicht (die Restzahl steht redundant im
2803
+ * Namenstext, siehe Story).
2804
+ */
2805
+ declare class AvatarStackComponent {
2806
+ /** Restzahl für den „+N“-Kreis (`.article-avatar-more`); 0 = kein Indikator. */
2807
+ readonly more: _angular_core.InputSignal<number>;
2808
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AvatarStackComponent, never>;
2809
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AvatarStackComponent, "cds-avatar-stack", never, { "more": { "alias": "more"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2810
+ }
2811
+
2812
+ /** Ein Eintrag der Breadcrumb-Leiste (`.article-breadcrumb`). */
2813
+ interface CdsArticleBreadcrumbItem {
2814
+ /** Sichtbarer Text. */
2815
+ label: string;
2816
+ /** Linkziel. Am letzten Eintrag wirkungslos, siehe Klassendoku. */
2817
+ href?: string;
2818
+ }
2819
+ /**
2820
+ * ArticleHeader (`cds-article-header`) — Wrapper um `.article-header` aus
2821
+ * css/components.css (css/components.css:1486–1490, 1508–1519): der zentrierte Kopf
2822
+ * eines Wissensbeitrags (Breadcrumb, optionale Pill, H1, Lead, Meta-Strip). Elftes
2823
+ * Ticket der Seitenbausteine-Serie. Hauptvorlage ist
2824
+ * `storybook-angular/src/docs/seitenmuster/wissensbeitrag.mdx`, Abschnitt „Article
2825
+ * Header“ — dort steht das für dieses Ticket verbindliche Markup samt Begründung,
2826
+ * nicht nur das Mockup in `docs/index.html`.
2827
+ *
2828
+ * **Breadcrumb sitzt im Header — abweichend von der allgemeinen Navigationsregel,
2829
+ * bewusst der Ticket-Vorlage folgend.** `docs/index.html:2423` dokumentiert für
2830
+ * Unterseiten allgemein, wörtlich: „Den Breadcrumb nicht in einen zentrierten
2831
+ * `.article-header` einbetten, sonst wird er mittig ausgerichtet und bekommt einen
2832
+ * abweichenden Abstand zur Nav“ (Tabellenzeile „Nicht“ der Breadcrumb-Doku) — und
2833
+ * ausgezählt
2834
+ * sind es genau die beiden EINZIGEN vollständigen Beispielseiten mit
2835
+ * `.article-header` (Stellenanzeige `docs/index.html:11035`, Wissensbeitrag · KI
2836
+ * `docs/index.html:15020`), die dieser Regel folgen: beide setzen den Breadcrumb in
2837
+ * eine EIGENE, linksbündige `.ep-section` VOR dem Header (`docs/index.html:
2838
+ * 11023–11031` bzw. `15010–15015`). Dem stehen 6 ISOLIERTE Doku-Demos gegenüber, die
2839
+ * den Breadcrumb INNERHALB von `.article-header` zeigen: 5 kleine Referenz-Boxen in
2840
+ * der Doku-Sektion selbst (`docs/index.html:7850`, `8304`, `8331`, `8361`, `8392` —
2841
+ * ohne Topnav/Hero/Footer, reine Bauteil-Illustrationen) plus das Code-Beispiel in
2842
+ * `wissensbeitrag.mdx`. Das Ticket benennt genau diese Doku (nicht die
2843
+ * Beispielseiten) als Hauptvorlage. Diese Komponente folgt der Ticket-Vorgabe
2844
+ * (Breadcrumb als Input, im Header) und dokumentiert den Widerspruch als eigenen
2845
+ * Befund
2846
+ * (`.scratch/angular-seitenbausteine/issues/20-breadcrumb-in-oder-vor-article-header.md`).
2847
+ * Konsumenten, die der allgemeinen Regel folgen wollen (wie die beiden echten
2848
+ * Beispielseiten), lassen `breadcrumb` leer und setzen die Leiste selbst davor
2849
+ * (siehe Story „Ohne Breadcrumb“).
2850
+ *
2851
+ * **Letzter Breadcrumb-Eintrag immer ohne Link, mit `aria-current="page"`** — so vom
2852
+ * Ticket als Akzeptanzkriterium gefordert. Die beiden Wissensbeitrag-Inline-Beispiele
2853
+ * (`docs/index.html:7850–7856`, `wissensbeitrag.mdx`) zeigen dafür nur 2 Einträge,
2854
+ * BEIDE als `<a>`, ohne `aria-current` — eine zur Kürze vereinfachte Doku-Skizze,
2855
+ * kein vollständiges Barrierefreiheits-Beispiel. Das volle, korrekte Muster (Trenner
2856
+ * dekorativ, letzter Eintrag `<span aria-current="page">` ohne Link) steht an
2857
+ * anderer Stelle exakt so vor (`docs/index.html:2406–2412` allgemeine
2858
+ * Breadcrumb-Doku, `docs/index.html:11023–11030` Stellenanzeige) und ist zusätzlich
2859
+ * eine explizite Akzeptanzbedingung des Tickets — die Komponente folgt deshalb
2860
+ * diesem Muster für den letzten Array-Eintrag, unabhängig von einem dort eventuell
2861
+ * gesetzten `href`.
2862
+ *
2863
+ * **Keine bereichsgefärbte Breadcrumb-Verlinkung (`.t-{area}`).** Die
2864
+ * Inline-Beispiele färben ihren zweiten (dort letzten) Eintrag mit `.t-ki`/`.t-es`/
2865
+ * `.t-wo`; das Ticket sieht dafür aber kein API-Feld vor (`{label, href?}`, kein
2866
+ * `area` pro Eintrag), und eine Zuordnung „Bereichsfarbe auf den vorletzten
2867
+ * Eintrag“ wäre geraten, nicht aus der Doku ableitbar — zumal der gefärbte Eintrag
2868
+ * dort ein Link ist, kein `aria-current`-Element, also nicht deckungsgleich mit dem
2869
+ * oben umgesetzten Muster. Bleibt bewusst außen vor.
2870
+ *
2871
+ * **Pill über `cds-pill`, kein direkt komponiertes `<span class="pill">`.** Geprüft
2872
+ * per `npx storybook tools docs show --id komponenten-chips-badges-pills-pill`:
2873
+ * `PillComponent`s Host ist `<cds-pill>`, `.pill` sitzt eine Ebene darunter auf
2874
+ * einem inneren `<span>` (anders als bei `FeaturedCardComponent`, wo genau das wegen
2875
+ * `.card-featured-body>.pill`-Kindselektoren nicht ginge). `.article-header`/`.pill`
2876
+ * haben keinen solchen Kindselektor (css/components.css:1486–1507 geprüft) — die
2877
+ * zusätzliche Ebene ist hier folgenlos, deshalb bleibt `cds-pill` als echte
2878
+ * Komponente eingesetzt, keine Klassen-Duplikation nötig.
2879
+ *
2880
+ * **Pille rendert nur, wenn `area` UND `pill` gesetzt sind — kein erfundener
2881
+ * Default.** `PillComponent.area` ist als `CdsArea` mit einem eigenen Default
2882
+ * (`'ki'`) typisiert; diese Komponente führt `area` dagegen als `CdsArea | undefined`
2883
+ * (keine Konfigurations-Vorgabe laut Ticket-API). Ein erster Entwurf reichte
2884
+ * `area()` per `as CdsArea`-Cast durch, damit ein `undefined`-Binding
2885
+ * `cds-pill`s eigenen Default überschreiben kann — eine Typ-Lüge, um einen Fall
2886
+ * abzudecken, der beim Nachzählen gar nicht vorkommt: **alle 9** `.pill`-Vorkommen
2887
+ * im Article-Header-Kontext (`docs/index.html:7856, 7912–7914, 8310, 8337, 8367,
2888
+ * 8398, 15021`) tragen ein `data-area`, keines ohne Bereich. Die Pille rendert
2889
+ * deshalb nur innerhalb von `@if (area(); as pillArea)` (narrowt `CdsArea |
2890
+ * undefined` sauber auf `CdsArea`, ohne Cast) — ist `pill()` gesetzt, `area()`
2891
+ * aber nicht, bleibt die Pille schlicht weg, statt eine geratene Bereichsfarbe zu
2892
+ * zeigen. Gepinnt in der Story „Pille ohne Bereich“.
2893
+ *
2894
+ * **`pillAriaLabel`, wie bei `FeaturedCardComponent`.** `PillComponent`s eigener
2895
+ * Default („Bereich `<label>`“) passt nur, wenn die Pille einen Bereichsnamen trägt
2896
+ * (Stellenanzeige, `docs/index.html:11036`: „Bereich Effektive Software“). Im
2897
+ * Wissensbeitrag trägt die Pille dagegen die Lesezeit (`wissensbeitrag.mdx`,
2898
+ * Abschnitt „Pill · Lesezeit“: `aria-label="Lesezeit 8 Minuten"`) — ein Text, den
2899
+ * die Komponente nicht zuverlässig aus einem freien `pill`-String wie
2900
+ * „8 min Lesezeit“ herleiten kann (keine Zahl zu parsen, keine Garantie, dass der
2901
+ * Text überhaupt eine Lesezeit ist). `pillAriaLabel` bleibt deshalb optional, ohne
2902
+ * eigenen Default: ungesetzt geht `undefined` direkt an `cds-pill`s `ariaLabel`
2903
+ * durch, das dann auf seinen eigenen Default („Bereich `<pill>`“) zurückfällt —
2904
+ * keine Logik-Duplikation nötig, weil hier die echte `PillComponent` verwendet
2905
+ * wird, keine Klassen-Nachbildung.
2906
+ *
2907
+ * **`date`/`dateLabel` getrennt, ANDERS als `cds-stoerer`.** `cds-stoerer`
2908
+ * formatiert ein reines ISO-Datum selbst nach `de-DE`
2909
+ * (`stoerer.component.ts:formattedDate`, inkl. manuellem Aufbau der
2910
+ * `Date`-Komponenten gegen den UTC-Mitternacht-Fallstrick von `new Date(iso)`).
2911
+ * Diese Komponente tut das NICHT: `date` liefert nur den maschinenlesbaren
2912
+ * `datetime`-Wert, `dateLabel` die sichtbare Schreibweise — vom Ticket ausdrücklich
2913
+ * als zwei getrennte Inputs vorgegeben. Begründung der Abweichung: Erstens deckt
2914
+ * sich das mit jeder realen Instanz (6 von 6 `.article-meta-date`-Vorkommen tragen
2915
+ * einen redaktionell gesetzten Text wie „13. Mai 2026“, keinen von
2916
+ * `Intl.DateTimeFormat` erzeugten) — anders als der Störer, dessen Kacheln NUR ein
2917
+ * ISO-Datum ohne separaten Text führen. Zweitens umgeht die Trennung den
2918
+ * Zeitzonen-Fallstrick vollständig, statt ihn zu beheben: ohne eigene Formatierung
2919
+ * konstruiert diese Komponente nie ein `Date`-Objekt aus `date()`, die
2920
+ * UTC-Mitternacht-Falle kann hier gar nicht erst auftreten. Ist `dateLabel` leer,
2921
+ * zeigt die Komponente `date()` unverändert als sichtbaren Text (bewusst als
2922
+ * ISO-Form, nicht geraten formatiert) — in der Story „Interaktiv“ als Warnfall extra
2923
+ * benannt, damit niemand das versehentlich auf eine Produktionsseite bringt.
2924
+ *
2925
+ * **Meta-Strip nur, wenn es etwas zu zeigen gibt.** `authorName`/`date` sind laut
2926
+ * Ticket-API Beiwerk (Default `''`); ausgezählt haben alle 6 realen
2927
+ * `.article-meta`-Vorkommen sowohl Autor als auch Datum, eine Stellenanzeige
2928
+ * (`docs/index.html:11035`) nutzt `.article-header` dagegen KOMPLETT OHNE
2929
+ * `.article-meta` (dort ein `<dl>` aus Job-Fakten statt Autor/Datum) — dieser
2930
+ * abweichenden Verwendung folgt diese Komponente nicht (sie hat in der Ticket-API
2931
+ * keinen Platz), sie belegt aber, dass ein leerer Meta-Strip ein realer Fall ist.
2932
+ * `.article-meta` (und darin `.article-meta-author`/`.article-meta-sep`) rendern
2933
+ * deshalb nur, wenn `authorName()` bzw. `date()` tatsächlich etwas liefern; der
2934
+ * Trenner nur, wenn beide Seiten vorhanden sind.
2935
+ *
2936
+ * **Avatar projiziert über `[cdsAvatar]`, PLUS `cds-avatar-stack`.** Die
2937
+ * Ticket-Skizze nennt nur `<ng-content select="[cdsAvatar]">`; ergänzt um den
2938
+ * Tag-Selektor `cds-avatar-stack`, weil `AvatarStackComponent` (siehe dort) ein
2939
+ * Element-Selektor ist, kein `[cdsAvatar]`-Attribut trägt und sonst nicht in den
2940
+ * Meta-Strip projiziert werden könnte — nötig für die vom Ticket geforderte Story
2941
+ * „Mehrere Autor:innen“.
2942
+ *
2943
+ * **Host als Block.** `.article-header` sitzt am Host und setzt nur
2944
+ * `max-width:880px;margin:0 auto`. An einem unbekannten, also `display:inline`
2945
+ * gerenderten Element greift beides nicht, die Block-Kinder liefen über die
2946
+ * 880 px hinaus. `:host{display:block}` wie bei `cds-hero-image` und
2947
+ * `cds-footer-main`; Story „Breite begrenzt“ pinnt das.
2948
+ */
2949
+ declare class ArticleHeaderComponent {
2950
+ /** Titel (`.article-title`, `<h1>`). */
2951
+ readonly title: _angular_core.InputSignal<string>;
2952
+ /** Anreißer unter dem Titel (`.article-lead`), leer = kein Lead. */
2953
+ readonly lead: _angular_core.InputSignal<string>;
2954
+ /** Breadcrumb-Pfad; letzter Eintrag rendert ohne Link mit `aria-current="page"`. */
2955
+ readonly breadcrumb: _angular_core.InputSignal<CdsArticleBreadcrumbItem[]>;
2956
+ /** Pille über dem Titel (`.pill`, via `cds-pill`), leer = keine Pille. */
2957
+ readonly pill: _angular_core.InputSignal<string>;
2958
+ /** `aria-label` der Pille überschreiben, siehe Klassendoku. */
2959
+ readonly pillAriaLabel: _angular_core.InputSignal<string | undefined>;
2960
+ /** Markenbereich → `data-area` der Pille; ungesetzt = keine Pille (siehe Klassendoku). */
2961
+ readonly area: _angular_core.InputSignal<CdsArea | undefined>;
2962
+ /** Name im Meta-Strip (`.article-meta-name`), leer = kein Meta-Strip-Autorblock. */
2963
+ readonly authorName: _angular_core.InputSignal<string>;
2964
+ /** Rolle im Meta-Strip (`.article-meta-role`), leer = keine Rollenzeile. */
2965
+ readonly authorRole: _angular_core.InputSignal<string>;
2966
+ /** ISO-Datum (`JJJJ-MM-TT`) → `<time datetime>`, leer = kein Datum. */
2967
+ readonly date: _angular_core.InputSignal<string>;
2968
+ /** Sichtbare Schreibweise des Datums; leer = `date` steht unverändert sichtbar. */
2969
+ readonly dateLabel: _angular_core.InputSignal<string>;
2970
+ /** @internal */
2971
+ protected readonly hasAuthor: _angular_core.Signal<boolean>;
2972
+ /** @internal */
2973
+ protected readonly hasDate: _angular_core.Signal<boolean>;
2974
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ArticleHeaderComponent, never>;
2975
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArticleHeaderComponent, "cds-article-header", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "lead": { "alias": "lead"; "required": false; "isSignal": true; }; "breadcrumb": { "alias": "breadcrumb"; "required": false; "isSignal": true; }; "pill": { "alias": "pill"; "required": false; "isSignal": true; }; "pillAriaLabel": { "alias": "pillAriaLabel"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "authorName": { "alias": "authorName"; "required": false; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": false; "isSignal": true; }; "date": { "alias": "date"; "required": false; "isSignal": true; }; "dateLabel": { "alias": "dateLabel"; "required": false; "isSignal": true; }; }, {}, never, ["[cdsAvatar], cds-avatar-stack"], true, never>;
2976
+ }
2977
+
2978
+ /** Ein Eintrag des Inhaltsverzeichnisses (`.article-toc-list li`). */
2979
+ interface CdsArticleTocItem {
2980
+ /** Sichtbarer Linktext, i. d. R. die Überschrift des Abschnitts. */
2981
+ label: string;
2982
+ /** Sprungziel, i. d. R. der Anker der zugehörigen `<h2>` im Article Body. */
2983
+ href: string;
2984
+ }
2985
+ /**
2986
+ * ArticleToc (`cds-article-toc`) — Wrapper um `.article-toc*` aus css/components.css
2987
+ * (css/components.css:1577–1589): das aufklappbare Inhaltsverzeichnis am Anfang eines
2988
+ * Wissensbeitrags. Zwölftes Ticket der Seitenbausteine-Serie („Artikel-Körper“).
2989
+ * Ausgezählt: genau 2 reale Vorkommen, beide mit 5 Einträgen und identischem
2990
+ * sichtbarem Text „Inhalt“ plus identischem `aria-label`
2991
+ * (`docs/index.html:7948–7960`, Doku-Sektion mit Platzhalter-Hrefs `#gt-article-toc`;
2992
+ * `docs/index.html:15049–15061`, reale Beispielseite Wissensbeitrag · KI mit echten
2993
+ * Abschnittsankern wie `#wb-ki-demo`).
2994
+ *
2995
+ * **Element-Selektor, ADR-0008-Standardfall.** `.article-toc` sitzt in beiden
2996
+ * Vorkommen als gewöhnlicher Block-Nachfahre direkt in `.article-body`
2997
+ * (`docs/index.html:7950`, `15051` je eine Ebene über dem `<details>`) — kein
2998
+ * Grid-/Flex-Kind, keine Layout-Klasse (`col-*`) vom Konsumenten, kein
2999
+ * Geschwister-Kombinator (`.article-toc` kommt in keiner CSS-Regel mit `+`/`~`
3000
+ * vor), kein Tag-Wechsel (immer `<details>`). Keines der drei ADR-0008-Kriterien
3001
+ * greift; ein Attributselektor brächte hier nichts. Die einzige direkte
3002
+ * Kind-Regel von `.article-body` (`.article-body > p`, css/components.css:1566)
3003
+ * zielt auf `p`, nicht auf `details` — ein `<cds-article-toc>`-Host zwischen
3004
+ * `.article-body` und dem `<details>` bricht deshalb keine Selektorkette.
3005
+ *
3006
+ * **Natives `<details>`/`<summary>`, kein nachgebautes Disclosure** (Ticket-Vorgabe,
3007
+ * Akzeptanzkriterium): Tastaturbedienung (Enter/Space auf `<summary>`) und
3008
+ * Toggle-Zustand kommen vollständig vom Browser, das CSS hängt direkt an `[open]`
3009
+ * (`.article-toc[open] .article-toc-caret`, css/components.css:1583). `<details
3010
+ * class="article-toc">` sitzt deshalb im TEMPLATE, nicht am Host — derselbe Grund
3011
+ * wie bei `cds-compare`s `<details class="ep-compare">` (`compare.component.ts`):
3012
+ * ein `<cds-article-toc>`-Host ist ein unbekanntes Custom Element und kann native
3013
+ * Disclosure-Semantik nicht annehmen.
3014
+ *
3015
+ * **Zweites Vorkommen des `<details>`-mit-drehendem-Caret-Musters, nicht
3016
+ * zusammengezogen mit `cds-compare` (ADR-0007 §5).** Beide Bauteile teilen die
3017
+ * Form (natives `<details>`, SVG-Caret, `[open]`-Rotation über
3018
+ * `transition:transform`), aber nicht die Aufgabe: `cds-compare` trägt eine
3019
+ * Vergleichstabelle mit `columns`/`rows`/`toggled`-Output, dieses Bauteil trägt
3020
+ * eine reine Link-Liste ohne Output (siehe API-Vorgabe des Tickets, die für dieses
3021
+ * Bauteil bewusst keinen `toggled` vorsieht). Zwei gleiche Stellen sind ein
3022
+ * Zufall, kein Muster — eine gemeinsame Basisklasse für zwei Vorkommen hätte nur
3023
+ * das `<details>`+Caret-Skelett gebündelt und dabei entweder Verhalten
3024
+ * vereinheitlicht (ein erzwungener `toggled`-Output ohne Zweck hier) oder so viel
3025
+ * parametrisiert, dass nichts gewonnen wäre.
3026
+ *
3027
+ * **`aria-label` am `<summary>` ist fest verdrahtet, kein Input.** Ausgezählt:
3028
+ * beide realen Vorkommen tragen wortgleich
3029
+ * `aria-label="Inhaltsverzeichnis ein- und ausklappen"` — der sichtbare Text
3030
+ * „Inhalt“ (`summary`-Input) allein wäre außerhalb des Beitragskontexts nicht
3031
+ * eindeutig, das `aria-label` schreibt deshalb aus, was das Element tut. Genau
3032
+ * dieser Wortlaut aus dem Mockup übernommen, kein erfundener zugänglicher Name.
3033
+ *
3034
+ * **Keine Nummerierung im Markup.** Die sichtbaren Ziffern vor jedem Eintrag
3035
+ * kommen aus `counter(toc)` auf `.article-toc-list li::before`
3036
+ * (css/components.css:1586), nicht aus dem `<ol>`-Default (`list-style:none` setzt
3037
+ * ihn zurück) — die Komponente muss dafür nichts weiter tun als `<ol
3038
+ * class="article-toc-list">` zu rendern.
3039
+ */
3040
+ declare class ArticleTocComponent {
3041
+ /** Sichtbarer Text im `<summary>`, z. B. „Inhalt“. */
3042
+ readonly summary: _angular_core.InputSignal<string>;
3043
+ /** Anfangszustand des `<details>` — reine Vorbelegung, kein Zwei-Wege-Zustand. */
3044
+ readonly open: _angular_core.InputSignal<boolean>;
3045
+ /** Abschnitte des Beitrags, in Anzeige-Reihenfolge. */
3046
+ readonly items: _angular_core.InputSignal<CdsArticleTocItem[]>;
3047
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ArticleTocComponent, never>;
3048
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArticleTocComponent, "cds-article-toc", never, { "summary": { "alias": "summary"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
3049
+ }
3050
+
3051
+ /**
3052
+ * ArticleCallout (`cds-article-callout`) — Wrapper um `.article-callout*` aus
3053
+ * css/components.css (css/components.css:1591–1600): der bereichsgetönte
3054
+ * Aside-Block für Praxis-Beispiele und „In der Realität“-Einschübe im Lauftext
3055
+ * eines Wissensbeitrags. Zwölftes Ticket der Seitenbausteine-Serie
3056
+ * („Artikel-Körper“). Ausgezählt: 5 reale Vorkommen, je eines pro Bereich in der
3057
+ * Doku-Sektion (`docs/index.html:8086–8115`, co/ki/es/wo) plus eines in der realen
3058
+ * Beispielseite Wissensbeitrag · KI (`docs/index.html:15110–15114`).
3059
+ *
3060
+ * **Element-Selektor, ADR-0008-Standardfall.** `.article-callout` sitzt in allen 5
3061
+ * Vorkommen als gewöhnlicher Block-Nachfahre — die 4 Doku-Boxen je in einem
3062
+ * schlichten `<div>` innerhalb eines `display:flex;flex-direction:column`-Stapels
3063
+ * (kein Stretch-Bedarf in Spaltenrichtung), die reale Instanz direkt in
3064
+ * `.article-body`. Keines ist ein Grid-/Flex-Kind mit Streckungsbedarf, keines
3065
+ * trägt eine `col-*`-Klasse, `.article-callout` kommt in keiner CSS-Regel mit
3066
+ * einem Geschwister-Kombinator (`+`/`~`) vor, das Tag variiert nicht (immer
3067
+ * `<aside>`). Keines der drei ADR-0008-Kriterien greift. Die einzige direkte
3068
+ * Kind-Regel von `.article-body` (`.article-body > p`, css/components.css:1566)
3069
+ * zielt auf `p`, nicht auf `aside` — ein `<cds-article-callout>`-Host zwischen
3070
+ * `.article-body` und dem `<aside>` bricht deshalb keine Selektorkette.
3071
+ *
3072
+ * **Projizierte Absätze bleiben direkte Kinder von `.article-callout`, kein
3073
+ * `<div>` um `<ng-content>`** (Ticket-Vorgabe: `.article-callout > p` ist ein
3074
+ * Kindselektor, css/components.css:1600). `<ng-content>` selbst fügt kein
3075
+ * DOM-Element ein — es verschiebt nur die vom Konsumenten geschriebenen
3076
+ * `<p>`-Elemente an ihre Stelle direkt im `<aside>`, eine Ebene unter dem
3077
+ * `<cds-article-callout>`-Host, aber ohne zusätzlichen Knoten dazwischen. Geprüft
3078
+ * im laufenden Storybook (Story „Interaktiv“, Play-Funktion):
3079
+ * `aside.article-callout > p` liefert sowohl die Eyebrow als auch jeden
3080
+ * projizierten Absatz, `:scope > *` zählt keine fremde Zwischenebene.
3081
+ *
3082
+ * **`eyebrow` ist Beiwerk (Default `''`), `area` ist Konfiguration mit
3083
+ * verteidigbarer Vorgabe (`'co'`).** Die Basisregel `.article-callout` selbst
3084
+ * (ohne `[data-area]`) rendert bereits exakt wie `[data-area="co"]`
3085
+ * (`background:var(--co-50)`, `border-left-color:var(--co-500)`, beide Werte
3086
+ * identisch an beiden Stellen, css/components.css:1591–1592) — `'co'` ist damit
3087
+ * keine erfundene Markenfarbe, sondern der reale CSS-Fallback ohne Attribut.
3088
+ * Anders als bei `cds-pill` (dessen `.pill` ohne `data-area` gar keine Füllfarbe
3089
+ * hat) gibt es hier keinen sinnvollen „kein Bereich“-Zustand.
3090
+ *
3091
+ * **Bekannter CSS-Befund, nicht im Wrapper geflickt (ADR-0001):**
3092
+ * `.article-callout-eyebrow` (Spezifität 0,1,0) verliert gegen
3093
+ * `.article-callout > p` (Spezifität 0,1,1, css/components.css:1600), weil die
3094
+ * Eyebrow selbst ein `<p>` UND ein direktes Kind von `.article-callout` ist.
3095
+ * Gemessen in rohem Markup ohne Angular (Playwright/Chromium,
3096
+ * `getComputedStyle`): die Eyebrow rendert in JEDEM Bereich mit `font-size:16px`
3097
+ * statt `12px` und `margin-bottom:0` statt `4px`; die Akzentfarbe geht zusätzlich
3098
+ * verloren, wenn kein bereichsspezifischer Override existiert (`co` und „kein
3099
+ * `data-area`“ zeigen `--tx-primary` statt `--co-700`). Diese Komponente
3100
+ * reproduziert exakt die Klassen und die Struktur des Mockups und zeigt deshalb
3101
+ * denselben, vorbestehenden Fehler wie rohes HTML — siehe
3102
+ * `.scratch/angular-seitenbausteine/issues/22-css-luecke-callout-eyebrow-spezifitaet.md`.
3103
+ *
3104
+ * **`aria-labelledby` auf `<aside>`, sobald `eyebrow` gesetzt ist — Zusatz zum
3105
+ * Mockup, keine CSS-Änderung.** `<aside>` hat implizit die Landmark-Rolle
3106
+ * `complementary`; ein Wissensbeitrag mit mehr als einem Callout hat damit
3107
+ * mehrere gleichnamige Landmarks ohne zugänglichen Namen. Gemessen mit
3108
+ * axe-core an rohem Markup ohne Angular (zwei `<aside class="article-callout">`
3109
+ * ohne Auszeichnung): `landmark-unique` schlägt fehl, unabhängig von dieser
3110
+ * Komponente — das Mockup selbst kennt diese Auszeichnung nicht (siehe
3111
+ * `.scratch/angular-seitenbausteine/issues/23-doku-luecke-callout-landmark-label.md`).
3112
+ * Die Eyebrow ist bereits ein prägnanter, vom Redakteur gepflegter Kurztext
3113
+ * genau für diesen Zweck (z. B. „In der Praxis“) — sie bekommt deshalb eine
3114
+ * generierte `id`, auf die `aria-labelledby` zeigt, sobald sie existiert. Ohne
3115
+ * Eyebrow bleibt das `<aside>` unbenannt wie im Mockup: ein zugänglicher Name
3116
+ * ließe sich sonst nur aus dem projizierten Absatztext raten, und das wäre eine
3117
+ * erfundene Bezeichnung, keine reale.
3118
+ */
3119
+ declare class ArticleCalloutComponent {
3120
+ private readonly instanceId;
3121
+ /** Kicker über dem Absatztext (`.article-callout-eyebrow`), leer = keine Eyebrow. */
3122
+ readonly eyebrow: _angular_core.InputSignal<string>;
3123
+ /** Markenbereich → `data-area` (Hintergrund + Akzentfarbe), siehe Klassendoku. */
3124
+ readonly area: _angular_core.InputSignal<CdsArea>;
3125
+ /**
3126
+ * `id` der Eyebrow für `aria-labelledby`, nur wenn eine Eyebrow existiert —
3127
+ * siehe Klassendoku.
3128
+ *
3129
+ * @internal
3130
+ */
3131
+ protected readonly eyebrowId: _angular_core.Signal<string | null>;
3132
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ArticleCalloutComponent, never>;
3133
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArticleCalloutComponent, "cds-article-callout", never, { "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
3134
+ }
3135
+
3136
+ /**
3137
+ * ArticleFigure (`cds-article-figure`) — Wrapper um `.article-figure`/
3138
+ * `.article-figcaption` aus css/components.css (css/components.css:1573–1575):
3139
+ * das redaktionelle Inline-Bild mit optionaler Bildunterschrift im Lauftext eines
3140
+ * Wissensbeitrags. Zwölftes Ticket der Seitenbausteine-Serie („Artikel-Körper“).
3141
+ * Ausgezählt: 3 reale Vorkommen — Doku-Demo mit Caption
3142
+ * (`docs/index.html:8028–8031`), reales Body-Bild mit Caption in der Beispielseite
3143
+ * Wissensbeitrag · KI (`docs/index.html:15115–15118`, identischer Bild- und
3144
+ * Caption-Text wie die Doku-Demo) und ein dritter, captionsloser Sonderfall direkt
3145
+ * unter dem Article Header derselben Beispielseite (`docs/index.html:15040–15042`,
3146
+ * dazu unten mehr).
3147
+ *
3148
+ * **Element-Selektor, ADR-0008-Standardfall.** In allen 3 Vorkommen sitzt
3149
+ * `.article-figure` als gewöhnlicher Block-Nachfahre (zwei in `.article-body`,
3150
+ * eines direkt in einer eigenen `.ep-section`) — kein Grid-/Flex-Kind, keine
3151
+ * `col-*`-Klasse vom Konsumenten, kein Tag-Wechsel (immer `<figure>`), kein
3152
+ * Vorkommen von `.article-figure` mit einem Geschwister-Kombinator in
3153
+ * css/components.css. Die einzige direkte Kind-Regel von `.article-body`
3154
+ * (`.article-body > p`, css/components.css:1566) zielt auf `p`, nicht auf
3155
+ * `figure` — ein `<cds-article-figure>`-Host zwischen `.article-body` und dem
3156
+ * `<figure>` bricht deshalb keine Selektorkette.
3157
+ *
3158
+ * **`loading="lazy"` ist fest verdrahtet, kein Input — bewusst NUR der
3159
+ * In-Article-Fall, nicht der dritte Mockup-Beleg.** Ausgezählt tragen 2 der 3
3160
+ * Vorkommen `loading="lazy"` (die beiden Bilder MIT Caption, mittig im
3161
+ * Lauftext, „below the fold“ — genau der in `wissensbeitrag.mdx`, Abschnitt
3162
+ * „In-Article Figure“, dokumentierte Dos-Punkt). Das dritte Vorkommen
3163
+ * (`docs/index.html:15040–15042`) trägt stattdessen `loading="eager"
3164
+ * fetchpriority="high"` UND hat keine Caption — es ist das erste Bild direkt
3165
+ * unter dem Article Header (Kommentar im Mockup: „Hero-Bild auf Body-Breite …
3166
+ * identisches Bild wie Vorschaubild für Wiedererkennung“), sitzt außerhalb von
3167
+ * `.article-body` und bekommt seine 720-px-Breite über ein
3168
+ * Inline-`style="max-width:720px;margin:0 auto"` am Konsumenten, nicht über die
3169
+ * Komponente (Randbedingung 6 der Spec: Mockup-Inline-Styles wandern nicht in
3170
+ * den Wrapper). Die Ticket-API sieht dafür kein `loading`/`fetchpriority`-Input
3171
+ * vor; dieses Bauteil deckt deshalb den (häufigeren, dokumentierten) In-Body-Fall
3172
+ * ab. Für den Lead-Bild-Sonderfall bleibt `<figure class="article-figure">` roh
3173
+ * schreibbar oder — sofern die Semantik passt — `cds-hero-image` (Ticket 02) zu
3174
+ * prüfen.
3175
+ *
3176
+ * **`alt` und `caption` sind bewusst getrennte Pflicht-/Beiwerk-Inputs, keine
3177
+ * Prüfung auf inhaltliche Überschneidung.** `wissensbeitrag.mdx` dokumentiert die
3178
+ * beiden Rollen ausdrücklich als unterschiedliche Jobs
3179
+ * (Dont: „Alt-Text und Caption inhaltlich identisch, Screenreader liest
3180
+ * doppelt“) — Vorgabe an den Konsumenten, nicht etwas, das eine Wrapper-Komponente
3181
+ * zur Laufzeit sinnvoll erzwingen könnte.
3182
+ */
3183
+ declare class ArticleFigureComponent {
3184
+ /** Bildquelle. */
3185
+ readonly src: _angular_core.InputSignal<string>;
3186
+ /** Faktische Bildbeschreibung für Screenreader, siehe Klassendoku. */
3187
+ readonly alt: _angular_core.InputSignal<string>;
3188
+ /** Redaktionelle Bildunterschrift (`.article-figcaption`), leer = keine Caption. */
3189
+ readonly caption: _angular_core.InputSignal<string>;
3190
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ArticleFigureComponent, never>;
3191
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArticleFigureComponent, "cds-article-figure", never, { "src": { "alias": "src"; "required": true; "isSignal": true; }; "alt": { "alias": "alt"; "required": true; "isSignal": true; }; "caption": { "alias": "caption"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3192
+ }
3193
+
3194
+ /**
3195
+ * ArticlePullquote (`cds-article-pullquote`) — Wrapper um `.article-pullquote` aus
3196
+ * css/components.css (css/components.css:1608–1612): die typografische
3197
+ * Hervorhebung eines Satzes aus dem eigenen Lauftext eines Wissensbeitrags.
3198
+ * Zwölftes Ticket der Seitenbausteine-Serie („Artikel-Körper“). Ausgezählt: 2
3199
+ * reale Vorkommen, wortgleich, beide `data-area="ki"` — Doku-Demo
3200
+ * (`docs/index.html:8136`) und reale Beispielseite Wissensbeitrag · KI
3201
+ * (`docs/index.html:15075`).
3202
+ *
3203
+ * **Nicht `cds-blockquote` (`BlockquoteComponent`, `.bq`) — Ticket-Vorgabe, im
3204
+ * JSDoc beider Bauteile wechselseitig abgegrenzt.** Pull-Quote und Blockquote
3205
+ * teilen die typografische Familie (Serif, bereichsgefärbter Linksakzent in
3206
+ * `{area}-500`), aber nicht den Zweck, dokumentiert in `wissensbeitrag.mdx`,
3207
+ * Abschnitt „Pull-Quote gegen Blockquote“:
3208
+ *
3209
+ * | | Pull-Quote (dieses Bauteil) | Blockquote (`cds-blockquote`) |
3210
+ * |---|---|---|
3211
+ * | Wessen Stimme? | Der Beitrag zitiert sich selbst — ein Schlüsselsatz aus dem eigenen Lauftext | Eine dritte, benannte Person (Kund:in, Forschungsstimme, Branchen-Statement) |
3212
+ * | Attribution | Keine (`quote` ist der einzige Input) | Pflicht (`name`, `roleLabel`) |
3213
+ * | Hintergrund/Icon | Keiner — `quotes:none`, kein Quote-Icon, bewusst „offen“ statt umrahmt | Getönte Akzent-Box (`--bq-bg`) mit Quote-Icon (`.bq-icon`) |
3214
+ * | Tag | `<blockquote class="article-pullquote">` direkt, kein umschließendes `<figure>` | `<figure class="bq">` außen, `<blockquote>` (ohne eigene Klasse) innen für den Zitattext |
3215
+ *
3216
+ * Ein Self-Quote im eigenen Beitrag (Blockquote-Optik auf einem Satz des
3217
+ * Autors) wirkt sonst absurd — der Autor zitiert die Person, die den Beitrag
3218
+ * schreibt. Wer eine externe Stimme mit Namen und Rolle zeigen will, verwendet
3219
+ * `cds-blockquote`.
3220
+ *
3221
+ * **`quote` enthält die deutschen Anführungszeichen bereits als Teil des Texts,
3222
+ * die Komponente ergänzt keine.** `.article-pullquote{quotes:none}`
3223
+ * (css/components.css:1608) — es gibt keine `content:open-quote`/`close-quote`-Regel
3224
+ * in der CSS-Schicht, weder hier noch bei `.bq blockquote` oder
3225
+ * `.testimonial blockquote`. Ausgezählt stehen die Anführungszeichen in BEIDEN
3226
+ * realen Vorkommen als literale Zeichen im Text
3227
+ * („KI scheitert selten an der Technologie. …“), nicht CSS-generiert. Wie bei
3228
+ * `cds-compare`/`cds-table` ist Copy-Text Sache des Konsumenten (ADR-0007 §2) —
3229
+ * die Story liefert deshalb `quote` bereits mit „…“ (CONTRIBUTING.md §6), die
3230
+ * Komponente rendert den String unverändert, ohne eigene Anführungszeichen zu
3231
+ * erfinden.
3232
+ *
3233
+ * **Element-Selektor, ADR-0008-Standardfall.** `.article-pullquote` sitzt in
3234
+ * beiden Vorkommen als gewöhnlicher Block-Nachfahre in `.article-body` — kein
3235
+ * Grid-/Flex-Kind, keine `col-*`-Klasse vom Konsumenten, kein
3236
+ * Geschwister-Kombinator in css/components.css, kein Tag-Wechsel (immer
3237
+ * `<blockquote>`). Die einzige direkte Kind-Regel von `.article-body`
3238
+ * (`.article-body > p`, css/components.css:1566) zielt auf `p`, nicht auf
3239
+ * `blockquote` — ein `<cds-article-pullquote>`-Host zwischen `.article-body` und
3240
+ * dem `<blockquote>` bricht deshalb keine Selektorkette.
3241
+ *
3242
+ * **`area` ist Konfiguration mit verteidigbarer Vorgabe (`'co'`), keine
3243
+ * erfundene Bereichsfarbe.** Die Basisregel `.article-pullquote` selbst (ohne
3244
+ * `[data-area]`) setzt bereits exakt denselben Wert wie `[data-area="co"]`
3245
+ * (`border-left-color:var(--co-500)`, css/components.css:1608–1609) — `'co'` ist
3246
+ * damit der reale CSS-Fallback ohne Attribut, nicht geraten.
3247
+ */
3248
+ declare class ArticlePullquoteComponent {
3249
+ /** Hervorgehobener Satz, inklusive deutscher Anführungszeichen, siehe Klassendoku. */
3250
+ readonly quote: _angular_core.InputSignal<string>;
3251
+ /** Markenbereich → `data-area` (Linksakzent), siehe Klassendoku. */
3252
+ readonly area: _angular_core.InputSignal<CdsArea>;
3253
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ArticlePullquoteComponent, never>;
3254
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArticlePullquoteComponent, "cds-article-pullquote", never, { "quote": { "alias": "quote"; "required": true; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3255
+ }
3256
+
3257
+ /**
3258
+ * AuthorCard (`div[cdsAuthorCard]`) — Wrapper um `.author-card` aus css/components.css
3259
+ * (css/components.css:1602–1606): der Avatar-plus-Bio-Strip am Ende eines
3260
+ * Wissensbeitrags, einzeln oder mehrfach in `cds-author-card-group`. Dreizehntes und
3261
+ * letztes Ticket der Seitenbausteine-Serie. Ausgezählt: 17 reale Vorkommen in
3262
+ * `docs/index.html` — 4 einzelstehend (2 Doku-Demos `docs/index.html:8193,8207`, 1
3263
+ * Artikel-Demo `8424`, 1 reale Beispielseite `15179`) und 13 in fünf Gruppen (siehe
3264
+ * `AuthorCardGroupComponent`).
3265
+ *
3266
+ * **Attributselektor (ADR-0008), gemessen im `is-grid`-Fall statt nur hergeleitet.**
3267
+ * `.author-card-group.is-grid` (css/components.css:1555) ist `display:grid` ohne
3268
+ * eigenes `align-items` — der CSS-Default `stretch` gleicht die Kartenhöhen einer
3269
+ * Reihe deshalb NUR aus, wenn `.author-card` selbst das Grid-Kind ist. Spike-Story
3270
+ * (zwei Karten, 600-px-Raster, kurze gegen deutlich längere Bio, seither wieder
3271
+ * gelöscht) hat beide Varianten nebeneinander gebaut und mit `getBoundingClientRect()`
3272
+ * gemessen:
3273
+ *
3274
+ * | Variante | Grid-Kind (Tag) | `.author-card`-Höhen | Bio-Rect (kurz / lang) |
3275
+ * |---|---|---|---|
3276
+ * | Element-Selektor `<cds-author-card-naive>` | `CDS-AUTHOR-CARD-NAIVE`, 204/204 px (gestreckt) | **84 / 204 px** (ungleich) | 24×73 / 144×200 px |
3277
+ * | Attributselektor `div[cdsAuthorCardSpike]` | `DIV.author-card`, 204/204 px | **204 / 204 px** (gleich) | — |
3278
+ *
3279
+ * Beim Element-Selektor wird der UNSICHTBARE `<cds-author-card-naive>`-Host auf 204 px
3280
+ * gestreckt, die sichtbare `.author-card`-Box eine Ebene darunter bleibt bei ihrer
3281
+ * Inhaltshöhe (84 px) — exakt der Fehler aus ADR-0008 Fall 1. Mit dem Attributselektor
3282
+ * IST `.author-card` das Grid-Kind, `align-items:stretch` trifft direkt zu.
3283
+ *
3284
+ * **Ehrlicher Zusatz, anders als bei `cds-icon-card`: die Baseline-Screenshots beider
3285
+ * Spike-Varianten waren byte-identisch** (`sha1` gleich). `.author-card` trägt (anders
3286
+ * als `.ep-card`) weder Hintergrund noch Rahmen noch Schatten — der zusätzliche,
3287
+ * unsichtbare Leerraum unter der kurzen Bio malt in keiner der beiden Varianten ein
3288
+ * Pixel. Der Fehler ist damit heute rein strukturell (falsches Boxmodell, `getBoundingClientRect()`
3289
+ * auf `.author-card` lügt), nicht optisch sichtbar. Er wird real, sobald `.author-card`
3290
+ * künftig einen Rahmen/Hintergrund/Hover-Zustand bekommt, und er verfälscht schon
3291
+ * heute jede Messung/Positionierung, die sich auf die tatsächliche Kartenhöhe verlässt
3292
+ * (u. a. die Story „Als Raster“ unten, die genau das pinnt). Das ADR-0008-Kriterium
3293
+ * ist strukturell formuliert („die Stelle im DOM einnehmen, die es ohne Angular
3294
+ * einnähme“), nicht optisch — der Attributselektor bleibt deshalb die richtige Wahl,
3295
+ * obwohl der Effekt heute unsichtbar ist.
3296
+ *
3297
+ * **`area` ist bewusst NICHT Teil der API — CSS-Befund, nicht erfundene Konfiguration.**
3298
+ * Alle 17 realen `.author-card`-Vorkommen tragen `data-area`, und sowohl
3299
+ * `docs/index.html:8185` als auch `wissensbeitrag.mdx:199` behaupten wörtlich, das
3300
+ * färbe „nur den Avatar“. Ausgezählt gibt es aber in `css/components.css` (Light UND
3301
+ * Dark) KEINE einzige `.author-card[data-area="…"]`-Regel — weder direkt noch über
3302
+ * einen Nachfahren-Selektor auf `.article-avatar`, dessen eigene
3303
+ * `[data-area]`-Färbung (css/components.css:1523–1526) ein Element-Selektor auf dem
3304
+ * Avatar selbst ist, unabhängig vom Vorfahren. `data-area` auf `.author-card` ist
3305
+ * damit, gegen die Doku-Aussage, komplett wirkungslos — die Bereichsfarbe kommt
3306
+ * ausschließlich vom `area`-Input, den der Konsument direkt an das projizierte
3307
+ * `[cdsAvatar]` bindet (siehe unten). Ein `area`-Input, der hier nur `data-area` ohne
3308
+ * jede CSS-Wirkung setzt, wäre eine erfundene Konfiguration ohne Gegenwert — Befund
3309
+ * gemeldet, nicht im Wrapper geflickt (ADR-0001):
3310
+ * `.scratch/angular-seitenbausteine/issues/24-css-luecke-author-card-data-area.md`.
3311
+ *
3312
+ * **Avatar projiziert über `[cdsAvatar]`, wie bei `cds-article-header`.** Der
3313
+ * Konsument setzt Größe (`size="lg"`, css/components.css:1527) und Bereich
3314
+ * (`area="…"`) direkt am projizierten `<div cdsAvatar>` — diese Komponente reicht
3315
+ * nichts durch, exakt die Trennung, die `cds-article-header` bereits etabliert
3316
+ * (siehe dessen Klassendoku, Abschnitt „Avatar projiziert über `[cdsAvatar]`“).
3317
+ *
3318
+ * **Eyebrow als `<h3>`, nur wenn gesetzt** (Beiwerk, Default `''`) — deckungsgleich
3319
+ * mit allen 4 einzelstehenden realen Vorkommen: 2 tragen `<h3 class="author-card-eyebrow">`
3320
+ * (`docs/index.html:8196,8427`, „Über den Autor“/„Über die Autorin“, Ticket-Vorgabe:
3321
+ * eine Ebene unter dem `<h2>` des Article-Body), die anderen 2 (Doku-Demos ohne
3322
+ * umgebende Artikelstruktur) haben gar keinen. Innerhalb einer Gruppe trägt laut
3323
+ * `wissensbeitrag.mdx` („Eyebrow-Konvention“) keine einzelne Karte mehr einen eigenen
3324
+ * Eyebrow — die Gruppen-Überschrift ersetzt sie (siehe `AuthorCardGroupComponent`);
3325
+ * Konsumenten lassen `eyebrow` dafür einfach leer.
3326
+ *
3327
+ * **`roleLabel`, NICHT `role` wie im Ticket-Text — gemessene Abweichung, kein
3328
+ * Freihand-Entscheid.** Ein erster Entwurf folgte der Ticket-API wörtlich
3329
+ * (`role`-Input, mit `role="…"` als schlichtem Attribut in den Stories gesetzt, wie
3330
+ * `name`/`bio`/`eyebrow`). Storybooks eingebauter a11y-Check (`aria-roles`) schlug
3331
+ * darauf für JEDE Story mit echtem Rollentext fehl: `role` ist ein globales
3332
+ * HTML-/ARIA-Attribut, und ein Angular-Input MIT DIESEM NAMEN wird bei einem
3333
+ * ungebundenen `role="Senior AI Engineer …"` zwar als Startwert an den Input
3334
+ * durchgereicht, bleibt aber ZUSÄTZLICH als echtes `role`-Attribut im DOM stehen —
3335
+ * axe meldete wörtlich „Roles must be one of the valid ARIA roles: Senior, AI,
3336
+ * Engineer, …“, weil der Freitext als ARIA-Rolle interpretiert wird. Exakt dieselbe
3337
+ * Kollision umgehen `BlockquoteComponent`, `TestimonialComponent` und
3338
+ * `TeamVoiceComponent` bereits mit `roleLabel` statt `role`
3339
+ * (`grep -rn "readonly role" angular-lib/projects/design-system-angular/src/lib/`
3340
+ * zeigt nur diese drei). Diese Komponente folgt demselben, bereits etablierten
3341
+ * Muster statt die Kollision ein viertes Mal zu wiederholen — CSS-Klasse bleibt
3342
+ * unverändert `.author-card-role`, nur der Input-Name weicht vom Ticket-Text ab.
3343
+ */
3344
+ declare class AuthorCardComponent {
3345
+ /** Name (`.author-card-name`). */
3346
+ readonly name: _angular_core.InputSignal<string>;
3347
+ /**
3348
+ * Rolle/Position (`.author-card-role`), leer = keine Rollenzeile. Heißt bewusst
3349
+ * `roleLabel`, nicht `role` (Kollision mit dem ARIA-Attribut `role`), siehe
3350
+ * Klassendoku.
3351
+ */
3352
+ readonly roleLabel: _angular_core.InputSignal<string>;
3353
+ /** Bio-Text (`.author-card-bio`), leer = kein Bio-Absatz. */
3354
+ readonly bio: _angular_core.InputSignal<string>;
3355
+ /** Kicker über dem Namen (`.author-card-eyebrow`, `<h3>`), leer = keine Eyebrow. */
3356
+ readonly eyebrow: _angular_core.InputSignal<string>;
3357
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AuthorCardComponent, never>;
3358
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AuthorCardComponent, "div[cdsAuthorCard]", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "roleLabel": { "alias": "roleLabel"; "required": false; "isSignal": true; }; "bio": { "alias": "bio"; "required": false; "isSignal": true; }; "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; }, {}, never, ["[cdsAvatar]"], true, never>;
3359
+ }
3360
+
3361
+ /**
3362
+ * AuthorCardGroup (`cds-author-card-group`) — Wrapper um `.author-card-group` aus
3363
+ * css/components.css (css/components.css:1547–1563): bündelt mehrere `[cdsAuthorCard]`
3364
+ * am Ende eines Wissensbeitrags, gestapelt (Default) oder als zweispaltiges Raster
3365
+ * (`is-grid`, css/components.css:1555). Dreizehntes und letztes Ticket der
3366
+ * Seitenbausteine-Serie. Ausgezählt: 5 reale Gruppen — 2 gestapelt in der
3367
+ * Artikel-Demo (`docs/index.html:8440,8465`, je 2 bzw. 3 Karten), 2 `is-grid`
3368
+ * (Doku-Demo `9112`, reale Beispielseite Scrum-Training `13811`, je 4 Karten) und 0
3369
+ * `is-grid`-Vorkommen im Wissensbeitrag selbst — `wissensbeitrag.mdx` verweist für
3370
+ * `is-grid` ausdrücklich auf `Seitenmuster/Seminar · Training`, „weil sie dort und
3371
+ * nicht in Wissensbeiträgen vorkommt“.
3372
+ *
3373
+ * **Element-Selektor, ADR-0008-Standardfall FÜR DIE GRUPPE SELBST** — anders als die
3374
+ * projizierte Karte. `.author-card-group` ist in keinem der 5 realen Vorkommen
3375
+ * selbst ein Grid-/Flex-Kind mit Streckungsbedarf (jedes sitzt direkt in einer
3376
+ * `.ep-section`/einem einfachen `<div>`), trägt nie eine `col-*`-Klasse vom
3377
+ * Konsumenten und kommt in keiner CSS-Regel mit einem Geschwister-Kombinator vor. Das
3378
+ * Tag variiert nicht (immer `<div>`). Ein `<cds-author-card-group>`-Host darüber
3379
+ * bricht deshalb selbst keine Selektorkette — die Karten dagegen brauchen ihren
3380
+ * eigenen Attributselektor, siehe `AuthorCardComponent`.
3381
+ *
3382
+ * **Die Klasse `.author-card-group` sitzt trotzdem NICHT auf dem Host, sondern auf
3383
+ * einem inneren `<div>` — das ist eine eigene, von den Karten unabhängige
3384
+ * Randbedingung.** Grund: `.author-card-group-eyebrow:has(+ .author-card-group.is-grid)`
3385
+ * (css/components.css:1563) ist ein Geschwister-Selektor: die Eyebrow-Überschrift
3386
+ * muss ein UNMITTELBARES Geschwister von `.author-card-group` sein, damit sie im
3387
+ * `is-grid`-Fall die breitere `max-width:960px` statt der Basis-`720px`
3388
+ * (css/components.css:1560) bekommt — sonst „sitzt sie bei der Raster-Variante 120 px
3389
+ * links neben der ersten Karte“ (Kommentar im CSS selbst). Läge `.author-card-group`
3390
+ * auf dem Host, könnte diese Komponente die Eyebrow nicht als Geschwister VOR dem
3391
+ * Host rendern (ein Angular-Template füllt ausschließlich das Innere seines eigenen
3392
+ * Hosts, nie dessen Umgebung) — die Eyebrow müsste dann ALS KIND in `.author-card-group`
3393
+ * selbst stehen und würde im Raster zur eigenen Grid-Zelle neben der ersten Karte,
3394
+ * sichtbar falsch. Mit der Klasse auf einem inneren `<div>` rendert das Template
3395
+ * `<h3 class="author-card-group-eyebrow">` und `<div class="author-card-group …">`
3396
+ * als echte, unmittelbare Geschwister IM Host `<cds-author-card-group>` — der
3397
+ * CSS-Selektor sieht nur diese beiden Geschwister, der zusätzliche äußere Host
3398
+ * ändert daran nichts, weil `:has(+ …)` ausschließlich den unmittelbaren
3399
+ * Elternknoten der beiden betrachtet, nicht dessen Vorfahren. Ohne diese zweite
3400
+ * Ebene bräuchte die Eyebrow denselben Attributselektor-Trick wie die Karte, obwohl
3401
+ * `.author-card-group` selbst kein Grid-/Flex-Kind ist — das eigentliche Problem hier
3402
+ * ist ein Geschwister-, kein Eltern-Kind-Kriterium, deshalb reicht die einfachere
3403
+ * Lösung (innere Klasse statt Host-Klasse).
3404
+ *
3405
+ * **Direkte Kinder bleiben gewahrt, `is-grid` inklusive.** `<ng-content>` fügt kein
3406
+ * eigenes Element ein: die projizierten `div[cdsAuthorCard]` (bereits selbst
3407
+ * `.author-card` am eigenen Host, siehe dort) landen unverändert als direkte Kinder
3408
+ * des inneren `.author-card-group`-`<div>` — Voraussetzung für den
3409
+ * Höhenausgleich im `is-grid`-Fall (`AuthorCardComponent`) und für den
3410
+ * Nachfahren-Selektor `.author-card-group .author-card` (css/components.css:1548).
3411
+ *
3412
+ * **`eyebrow` als `<h3>`, deckungsgleich mit den beiden realen, VOLLSTÄNDIGEN
3413
+ * Seiten-Vorkommen der gestapelten Variante** (`docs/index.html:8439,8464`, „Über die
3414
+ * Autor:innen“) — nicht mit der isolierten Doku-Illustration (`9111`, `<p>`,
3415
+ * dokumentiert ohne umgebende `<h2>`-Hierarchie). Die einzige reale `is-grid`-Seite
3416
+ * (Scrum-Training, `13811`) verzichtet auf die Gruppen-Eyebrow komplett, weil die
3417
+ * Sektion bereits `.ep-section-label` plus `<h2>` trägt — exakt der in
3418
+ * `wissensbeitrag.mdx` („Trägt die Sektion bereits ein `.ep-section-label` plus H2,
3419
+ * entfällt sie“) dokumentierte Fall. Konsumenten mit eigener Sektionsüberschrift
3420
+ * lassen `eyebrow` dafür leer, statt eine zweite `<h3>` zu erzwingen.
3421
+ *
3422
+ * **Konsequenz der inneren Klasse: der Host `<cds-author-card-group>` selbst trägt
3423
+ * weder `.author-card-group` noch `.is-grid`.** Ein `class`/`style` direkt am
3424
+ * `<cds-author-card-group>`-Tag landet auf dem unbekannten, standardmäßig
3425
+ * `display:inline` gerenderten Custom Element, NICHT auf der tatsächlichen
3426
+ * Layout-Box (dem inneren `<div>` mit `max-width`/Grid). Wer Layout-Eigenschaften
3427
+ * setzen will (z. B. `margin-top` wie im Trainer-Beispiel,
3428
+ * `docs/index.html:13811`), setzt sie am umgebenden Konsumenten-Markup, nicht am
3429
+ * Host — dieselbe Einschränkung, die ADR-0008 für Attributselektor-Komponenten
3430
+ * beschreibt, hier aber aus einem Geschwister- statt einem Eltern-Kind-Grund.
3431
+ */
3432
+ declare class AuthorCardGroupComponent {
3433
+ /** Gemeinsame Überschrift (`.author-card-group-eyebrow`, `<h3>`), leer = keine. */
3434
+ readonly eyebrow: _angular_core.InputSignal<string>;
3435
+ /** Zweispaltiges Raster statt gestapelter Liste (`.is-grid`). */
3436
+ readonly grid: _angular_core.InputSignal<boolean>;
3437
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AuthorCardGroupComponent, never>;
3438
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AuthorCardGroupComponent, "cds-author-card-group", never, { "eyebrow": { "alias": "eyebrow"; "required": false; "isSignal": true; }; "grid": { "alias": "grid"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
3439
+ }
3440
+
3441
+ export { AreaBadgeComponent, AreaTabComponent, AreaTabsComponent, ArticleCalloutComponent, ArticleFigureComponent, ArticleHeaderComponent, ArticlePullquoteComponent, ArticleTocComponent, AuthorCardComponent, AuthorCardGroupComponent, AvatarComponent, AvatarStackComponent, BlockquoteComponent, ButtonComponent, CDS_AREAS, CDS_AREA_LABELS, CDS_THEME_ICON, CDS_THEME_LABEL, CDS_THEME_ORDER, CardComponent, CarouselComponent, CheckboxComponent, ChipComponent, CodeBlockComponent, ComboboxComponent, CompareComponent, CtaBandComponent, DownloadCtaComponent, FactsComponent, FaqComponent, FeatureComponent, FeaturedCardComponent, FooterBottomComponent, FooterComponent, FooterMainComponent, HeroImageComponent, IconCardComponent, LinkCardComponent, LogoCarouselComponent, LogoComponent, PillComponent, RadioGroupComponent, ScaleComponent, SectionComponent, SelectComponent, SelectFieldComponent, SliderComponent, SnackbarComponent, StatCardComponent, StatStripComponent, StatusBadgeComponent, StoererComponent, StoererSetComponent, TableComponent, TeamVoiceComponent, TestimonialComponent, TextFieldComponent, TextareaFieldComponent, ThemeCycleComponent, ThemeModeService, ThemeSegmentComponent, ThemeSelectComponent, TierComponent, TopnavComponent, cdsThemeModes, themeStore };
3442
+ export type { CdsArea, CdsArticleBreadcrumbItem, CdsArticleTocItem, CdsAvatarSize, CdsBadgeTone, CdsButtonSize, CdsButtonVariant, CdsCompareColumn, CdsCompareRow, CdsFactsItem, CdsFaqItem, CdsFlatStat, CdsFooterLink, CdsLogo, CdsNavItem, CdsNavSubItem, CdsSelectOption, CdsSlide, CdsSnackTone, CdsSocialLink, CdsSocialPlatform, CdsThemeMode };