/* ==========================================================================
   ratenkredit-diagramm.min.css — "Zinskorridore" (Ratenkredit DE), Chrome & Grundoptik.

   Zweck: gesamte eigene Optik der dritten Ansicht des DE-Ratenkredit-Vergleichs —
   Buehne, Achse, Baender, Caps, Raute, Markt-Mittel-Linie, Legende, Sortier-Steuerung,
   Detailpanel, Pflichtblock, No-JS-Fallback — in BEIDEN Kontrast-Modi
   (Normal = dunkle Buehne #07203a, kontrast-hell = hell).

   TROTZ .min IM NAMEN KEIN MINIFIKAT. Die Diagramm-Ansichten laden unminifiziertes
   CSS; der Name haelt nur das Schema der Schwester-Dateien. Nicht minifizieren.

   Produktpraefix im Dateinamen ist zwingend: das Festgeld-Diagramm belegt im flachen
   Webroot bereits diagramm.min.css.

   Namensraum .zk- fuer alles Neue. Aus dem Bestand geerbte Klassen (#vergleich,
   #hilfe, .vergleich-dashboard, .laufzeit-nav/-pill, .filter-*, .toggle-*,
   .anpassen-*, .sidebar-filter-*, .results-header, .result-count, .kontrast-*,
   .ecke, .vergleich-footer, .footer-line) bleiben unpraefigiert und unveraendert —
   sie tragen zentrale Styles aus style.css und vergleich.min.css.

   Scoping-Anker der Ansicht ist die Zweitklasse .zinskorridore-dashboard am
   .vergleich-dashboard.

   Einheiten: em/rem, kein px (Projektkonvention). Zwei Ausnahmen, beide keine
   Abstaende: Haarlinien-Rahmen (1px, skaliert in em je nach Zoom auf 0 oder 2
   Geraetepixel) und der sr-only-Satz der Fallback-Tabelle (uebernommenes Idiom, das
   gerade NICHT mitskalieren soll). Der Cache-Bust-Stand steht bewusst NICHT hier —
   er wird gemessen, siehe Kasten am Ende dieses Kopfes.

   FARBEN: beide Paletten stehen als Custom Properties auf .zk-buehne und werden
   ueber #vergleich.kontrast-hell .zk-buehne komplett getauscht (E30, P§5). Keine
   Farbe wird von der Engine gesetzt — Phase 2 rendert serverseitig, das JS faerbt
   nichts. Die Werte sind rechnerisch belegt (siehe CHANGELOG Phase 2).

   --------------------------------------------------------------------------
   CHANGELOG

   Phase 1 (Fundament, 25.07.2026, ?v=1): Stub. Bewusst ohne Regeln.

   Phase 2 (Leiter statisch, 25.07.2026, ?v=2): Diagramm-Optik. Der .zk-Block aus
   dem Inline-<style> des Cores (Buehnen-Huelle, .zk-view-icon, sr-only-Regel der
   Fallback-Tabelle) ist hierher umgezogen — im Core steht ab jetzt nur noch das
   verbatim uebernommene Bedienleisten-CSS. Neu: zwei vollstaendige Paletten als
   Custom Properties, Achse mit Teilstrichen (sticky, rem-Metrik), Zeilenraster mit
   Label-Spalte, Baender mit Caps, Punkt-Darstellung fuer degenerierte Baender,
   Mint-Raute mit den vier Lagen (innen / Randlage / Ueberschreitung / Achsenrand),
   Konflikt-Spur, Staffel-Marker, Median-Linie mit Beschriftung, Punkt-Modus-Hinweis,
   Leerzustand.

   Phase 2, zweiter Bauteil (Pflichtangaben, 25.07.2026, WEITERHIN ?v=2 — kein
   zweiter Bump innerhalb derselben Phase): Legende (Abschnitt 10), § 17-Fussnote
   und Pflichtblock (Abschnitt 11/12), dazu .zk-zeile-bsp und .zk-sprung in
   Abschnitt 6. Zwei Aenderungen an Bestehendem:
     - Die Palettenbloecke (Abschnitt 1) tragen jetzt ZWEI Selektoren, .zk-buehne
       und .zk-legende. Custom Properties vererben nur nach unten; die Legende ist
       ein Geschwisterelement der Buehne und haette sonst keine Werte. Bewusst
       derselbe Regelblock statt einer zweiten Werteliste.
     - Nichts an Geometrie, Achse, Band, Raute oder Median wurde angefasst.
   Farbfuehrung der beiden Textbloecke bewusst NICHT ueber die zk-Palette, sondern
   ueber die Dashboard-Variablen (--text-primary/-secondary/-muted) wie beim
   Punkt-Modus-Hinweis: es ist Fliesstext auf Seitengrund, kein Diagrammteil, und
   er muss auch im Leerzustand lesbar sein. Das hat einen zweiten Grund: gemessen
   25.07.2026 tauscht vergleich.min.css diese Variablen unter kontrast-hell schon
   selbst (--text-primary #fff -> #111, --text-secondary -> rgba(0,0,0,0.88),
   --text-muted -> #404040, Grund -> #fff). Wer hier eigene Hexwerte setzte,
   baute eine zweite Wahrheit, die beim naechsten Bestands-Update auseinanderlaeuft.
   Deshalb nur ZWEI eigene Hell-Regeln: .beispiel-effzins und der Ruecksprung-Link,
   beide zeichengleich aus Liste und Tabelle uebernommen, weil eine dritte Optik
   derselben Pflichtangabe Cross-View-Drift waere.

   Phase 2, VRT-Nacharbeit (25.07.2026, WEITERHIN ?v=2 — kein Bump innerhalb
   derselben Phase): die zwei Befunde des visuellen Regressionstests, die live
   sichtbar waren.
     - B1 Achsenbeschriftung. Die Klemmung von erstem und letztem Label geht jetzt
       auf die Buehnen-AUSSENkante (0,75rem statt 0,1rem) und die Ausduennung
       laeuft ueber drei Dichtestufen, die der Core setzt (.zk-tick-weit/-mittel/
       -eng, Abschnitt 4 und 13). Die alte Regel nth-child(even):not(:last-child)
       in den beiden Media-Queries ist ersatzlos entfallen: sie konnte die ANZAHL
       der Teilstriche nicht sehen, griff deshalb bei 1200 px gar nicht (18 Labels,
       9 Ueberlappungen, schlimmster Fall -20,6 px) und duennte umgekehrt im
       Punkt-Modus aus, wo vier Teilstriche reichlich Platz haben.
     - B2 Sprungziel. .zk-zeile bekommt scroll-margin-top (Abschnitt 6), der
       Pflichtblock-Eintrag einen kleinen Vorsorgewert (Abschnitt 12).
   Nichts an Geometrie, Band, Raute, Median oder Palette wurde angefasst.

   KONTRAST DER TEXTBLOECKE, gemessen 25.07.2026 im Browser gegen den ECHTEN
   Seitengrund. Der ist #0070C0 (helles Blau) — nicht das Dunkelblau, das die
   Buehnenfarbe nahelegt. Daraus folgt eine harte Obergrenze:
     weiss (--text-primary) auf #0070C0 .................. 5,15:1
     --text-secondary rgba(255,255,255,0.7) .............. 3,32:1  (unter AA)
     --text-muted     rgba(255,255,255,0.5) .............. 2,40:1  (unter AA)
     Liste heute, .beispiel-text rgba(255,255,255,0.88) .. 4,35:1  (knapp unter AA)
   Fussnote und Pflichtblock laufen deshalb DURCHGAENGIG auf --text-primary; die
   Hierarchie tragen Groesse und Schnitt. Im Hell-Modus ist die Lage entspannt
   (#111 auf #fff = 18,88:1, #00528D = 8,10:1).
   Das heisst zugleich: Liste und Tabelle unterschreiten fuer denselben § 17-Text
   heute AA. Das ist ein Bestandsbefund, kein Ergebnis dieser Phase — hier nur
   notiert, nicht einseitig geaendert.
   Die Legende dagegen steht auf dem BUEHNEN-Grund: eine Farbprobe muss auf dem
   Untergrund stehen, den sie erklaert, sonst gilt der Kontrast-Nachweis nicht.
   Keine neue Farbe eingefuehrt — alle Proben ziehen aus den Custom Properties,
   der Kontrast-Nachweis oben gilt damit unveraendert.

   KONTRAST-NACHWEIS (200 Stuetzstellen ueber den Bandgradienten, WCAG-Rechner):
   Die Raute ist ein ZWEIFARBIGES Objekt (Fuellung + Kontur) — eine einfarbige Raute
   kann auf einem Hell-nach-Dunkel-Gradienten prinzipiell nicht tragen, weil jede
   Farbe irgendwo ihren Luminanz-Zwilling (1,00:1) hat. Geprueft wird, ob an jedem
   Punkt MINDESTENS EINE der beiden Komponenten >= 3:1 traegt.
     Mint-Raute      normal 3,64:1 auf Band / 13,23:1 auf Buehne · hell 5,72:1 / 8,00:1
     Konflikt-Raute  normal 3,14:1 auf Band /  9,84:1 auf Buehne · hell 5,72:1 / 9,90:1
     Cap             normal 10,13:1 · hell 16,45:1 (jeweils gegen die Buehne)
     Median-Linie    normal  9,68:1 · hell  5,80:1   (Apricot, seit Phase 3;
                     vorher Bernstein #ffd27f/#8a5a00 mit 11,57:1 · 5,93:1)
     Tick-Text       normal 10,76:1 · hell  6,92:1  (Schwelle 4,5)
     Achslinie       normal  5,17:1 · hell  3,55:1  (Schwelle 3)
     Typo primaer    normal 16,45:1 · hell 16,51:1
     Typo sekundaer  normal 10,76:1 · hell  8,49:1
   TEXT LIEGT NIE AUF DEM BAND: weisser Text auf dem hellen Bandbeginn erreicht nur
   2,27:1. Alle Zahlen und Notizen stehen deshalb in der Label-Spalte auf Buehnen-
   grund, nicht auf dem Band.
   Konflikt-Ton (E13) ist Violett — ausdruecklich nicht Rot (der Bestand kennt keine
   rote Ampelfarbe) und der einzige in der Palette unbelegte Farbwinkel, damit er von
   Raute (Mint), Median (Apricot) und Band (Blau) trennbar bleibt.

   --------------------------------------------------------------------------
   Phase 3 (Interaktion, 25.07.2026, ?v=3): die Optik der neuen Bedienelemente und
   die Median-Farbe.
     - MEDIAN AUF APRICOT (Anwender-Entscheid). --zk-median normal #ffd27f -> #ffb59e,
       hell #8a5a00 -> #b33e19. Beides sind die Werte des Apricot-Zweitakzents, den
       der Bestand am selben Tag ausgerollt hat (ratenkredit-vergleich-core.inc.php
       Z. 171-180). Kontraste neu gerechnet, siehe Tabelle oben — beide bleiben
       deutlich ueber 4,5:1. Es ist ein reiner Wertetausch in den zwei Paletten-
       bloecken; keine Regel, die --zk-median verwendet, wurde angefasst.
     - SORTIERLEISTE (Abschnitt 14) und TABELLEN-UMSCHALTER samt sichtbarer
       Textfassung (Abschnitt 15). Beide stehen AUSSERHALB der Buehne und damit
       ausserhalb ihrer Custom Properties; sie ziehen ihre Optik deshalb aus den
       Dashboard-Variablen und aus den Bestands-Bedienelementen (.toggle-group/
       .toggle-btn aus vergleich.min.css, .filter-reset-btn aus dem Inline-Block des
       Cores) — die Ansicht soll wie eine Schwester von Liste und Tabelle aussehen.
     - FLIP-GRUNDLAGEN (Abschnitt 16): zwei Custom Properties als Vertrag mit der
       Engine plus das prefers-reduced-motion-Pendant. Kein globales
       "transition: none", kein !important.
     - HOCHKONTRAST-HELL der neuen Bedienelemente (Abschnitt 17), zeichengleich zu
       den Bestands-Overrides im Inline-Block des Cores.
     - SCROLL-LOCK des Panel-Overlays (Abschnitt 18), zwei Zeilen. Die Engine setzt
       ab Phase 3 html.zk-overlay-locked; ohne Gegenstueck hier waere die Klasse
       wirkungslos und der Hintergrund scrollte unter dem offenen Panel weiter. Die
       uebrige Panel-Optik bleibt Phase 4.
   Nichts an Geometrie, Achse, Band, Raute oder Zeilenraster wurde angefasst.

   KONTRAST DER NEUEN BEDIENELEMENTE, gerechnet (nicht gemessen) gegen den oben
   dokumentierten, am 25.07.2026 gemessenen Seitengrund #0070C0:
     Segment inaktiv rgba(255,255,255,0.88) auf dem zusammengesetzten Leisten-
       grund rgba(0,82,141,0.4) ueber #0070C0 (= #0064AC) ......... 5,13:1
     Segment aktiv   #004578 auf #ffffff ......................... 9,90:1
     Segment aktiv hell #ffffff auf #0070C0 ...................... 5,15:1
     Label / Umschalter-Text --text-primary auf #0070C0 .......... 5,15:1
     alles hell auf #ffffff (#003A66) ........................... 11,69:1
   BEWUSSTE ABWEICHUNG VOM BESTAND: die Bestands-Bedienleiste faerbt ihre Labels
   mit rgba(255,255,255,0.85) (= 4,16:1, unter AA — Core-Inline-Block) bzw. mit
   --text-muted (2,40:1). Neue Beschriftungen laufen hier stattdessen auf
   --text-primary, wie es der Kopf oben schon fuer Fussnote und Pflichtblock
   festhaelt. Der Unterschied ist minimal sichtbar und ist der Preis dafuer, eine
   bekannte AA-Unterschreitung nicht in neues Markup zu kopieren.

   Phase 3, Nachtrag (Bedienleiste, 30.07.2026, ?v=4): KEINE Regel geaendert. Der
   Bump haelt allein den Lockstep mit Core und Engine, die den Fix der drei
   Bedienleisten-Defekte tragen (Engine-Kopf, Abschnitt 8b). Die Optik des
   "weitere Filter"-Overlays war nie hier zuhause: sie steht vollstaendig im
   Inline-Block des Cores (.anpassen-overlay / .anpassen-backdrop / .anpassen-panel,
   Z. 1021-1052 und 1355-1364), weil sie verbatim aus der Bestands-Bedienleiste
   uebernommen ist. Der Defekt lag ausschliesslich in der fehlenden .open-Klasse,
   also im JavaScript — hier war nichts zu reparieren, und ein Eingriff waere ein
   Duplikat der Core-Regeln gewesen. Der frueher hier etablierte Praezedenzfall
   "kein Bump innerhalb derselben Phase" (Phase 2, zweimal) galt nur, solange die
   Phase nicht hochgeladen war; ?v=3 ist live, damit ist er erloschen.

   Phase 3, Nachtrag zum Nachtrag (Partial-Tausch, 30.07.2026, gebaut unter ?v=4):
   EINE neue Regel,
   Abschnitt 19. Ein Filterwechsel tauscht seit der Nachbesserung
   .vergleich-dashboard als Ganzes; das Filter-Overlay liegt darin und wird
   danach sofort wieder geoeffnet. .zk-ohne-uebergang legt Backdrop- und
   Panel-Uebergang fuer diesen einen Frame stumm, damit die Einblend-Animation
   nicht bei jedem Haekchen erneut spielt — ueber Spezifizitaet (0,3,0 gegen
   0,1,0 der Core-Regeln), nicht ueber !important. Geometrie, Achse, Band, Raute
   und Zeilenraster bleiben auch hier unberuehrt.

   Phase 3, Abschluss (30.07.2026, ?v=5): AN DIESER DATEI KEINE REGEL GEAENDERT.
   Der Bump ist Lockstep-Pflicht — Core und Engine tragen Korrekturen der
   Review-Befunde B11, H16 und H11, und CSS, JS und Core werden nur gemeinsam
   versioniert.

   --------------------------------------------------------------------------
   Phase 4 (Panel-Inhalt, 31.07.2026, Bump auf ?v=6): die gesamte Optik des
   Detailpanels. Bis hierher hatte .zk-panel* KEINE einzige Regel — ein geoeffnetes
   Overlay rendete als gewoehnlicher Block im Textfluss (Recon A.8). Neu:
     - ABSCHNITT 20, Detailpanel: Overlay (position: fixed, KEIN backdrop-filter —
       E32 woertlich), Backdrop, Blau-Glas-Panel (rgba(9,87,143,0.92) +
       blur(1.25em), Mint-Kante, 30rem am Desktop, Bottom-Sheet <= 48em), Titel und
       scrollender Body, Leak-Resets fuer den Panel-Teilbaum, Reiterleiste mit
       Roving-Tabindex-Optik, Reiterflaechen (per [hidden], NICHT per .active —
       fokusZiele() filtert ueber offsetParent, Recon F3), Feldlisten, Zinsmatrix,
       Panel-Fuss mit CTA und Sprunganker, Hinweis nach E43.
     - ABSCHNITT 20b, ZEILEN-RESET: button.zk-zeile-flaeche ist seit E39a der
       Auslöser und liegt ZWISCHEN .zk-zeile und ihren beiden Kindern. Ohne Reset
       zerfaellt das Zeilenraster (Recon F7). Die Flaeche traegt deshalb jetzt
       selbst das .zk-raster-Spaltenmodell (Abschnitt 3 und 13, je ein Selektor
       ergaenzt) und spannt sich im aeusseren Raster ueber beide Spalten;
       a.zk-sprung steht als GESCHWISTER in Spalte 1 darunter und behaelt ein
       EIGENES Fokusbild (gepunktet + Mint-Chip gegen den durchgezogenen Ring der
       Flaeche), damit die zweite Station nicht als Wiederholung der ersten
       gelesen wird (E39a).
     - ABSCHNITT 20c, HOVER/FOKUS-KOPPLUNG: Band, Punkt und Raute sind Kinder der
       Flaeche und werden rein per CSS mitgehoben, ohne eine Zeile JS (Bauplan S7).
       :focus-visible statt :focus, damit ein Mausklick keinen Ring hinterlaesst.
       Die Hervorhebung laeuft ueber box-shadow, NICHT ueber transform oder
       Rahmenbreite: .zk-raute traegt bereits transform: rotate(45deg), und eine
       Layout-Aenderung an der Zeile waehrend eines FLIP-Laufs verschoebe die
       gemessenen Positionen. Der Pflichtblock-Eintrag ist KEIN Kind der Flaeche —
       ihn markiert die Engine mit .zk-beispiel-hervor, hier gestaltet.
     - NACHTRAG aus dem Core-Bauabschnitt, KEIN zweiter Bump (weiterhin ?v=6, die
       Fassung ist nicht ausgeliefert): .zk-staffel-zusatz (Betrags-/Staffelzusatz
       innerhalb eines Matrix- oder Sollzins-Wertes, Vorbild .staffel-zusatz der
       Liste) und die Zeile der gewaehlten Laufzeit im Zinsmatrix-Reiter. Letztere
       ist ueber .zk-zinsmatrix-zeile[aria-current] selektierbar — der Core hat
       dafuer bewusst keine Klasse erfunden. Ihre Hervorhebung traegt DREI
       Merkmale, von denen keines Farbe ist; die Information selbst steht ohnehin
       im sichtbaren Text und haengt an keiner CSS-Regel.
     - ABSCHNITT 21, HOCHKONTRAST-HELL des Panels und der Kopplung. Notwendig und
       nicht optional: --accent ist in vergleich.min.css ausschliesslich auf
       .vergleich-dashboard definiert, das Panel liegt AUSSERHALB davon (Recon A.4).
       var(--accent) faellt dort in BEIDEN Paletten auf den Mint-Fallback zurueck —
       auf weissem Panelgrund traegt Mint mit 1,24:1 nichts.
     - E44 PUNKT 1 (VRT-Befund N3): die Beschriftungen im "weitere Filter"-Panel
       standen in der dunklen Palette bei 4,48:1 (rgba(255,255,255,0.7) auf
       gemessenem rgb(8,89,147)) und verfehlten AA um 0,02. Angehoben auf
       rgba(255,255,255,0.82) = 5,51:1. Die Regel steht HIER und nicht im
       Inline-Block des Cores, weil dieser Bauabschnitt genau eine Datei aendert;
       sie gewinnt ueber Spezifizitaet (1,3,0 gegen 0,1,0), nie ueber !important,
       und klammert die helle Palette per :not(.kontrast-hell) aus — dort liegen
       dieselben Texte bereits bei 8,10:1 bzw. 12,63:1 und wuerden von einem
       Weisston zerstoert. Die LISTENANSICHT bleibt unveraendert; die dadurch
       entstehende Divergenz ist bewusst (E44) und gehoert in den Befund des
       cross-view-konsistenz-pruefer.
   Nichts an Achse, Band, Raute, Median, Palette oder Leiter-Geometrie wurde
   angefasst. .zk-spur behaelt position: relative; .zk-zeile bleibt bewusst
   statisch positioniert (die sticky Achse traegt z-index: 4 und muss ueber den
   Zeilen bleiben).

   KONTRAST DES PANELS, gerechnet gegen den GEMESSENEN Panelgrund rgb(8,89,147)
   (VRT Phase 3, Befund N3 — dieselbe Farbformel rgba(9,87,143,0.92) traegt auch
   das neue Panel). Der Wert ist die konservative Annahme: das Zinskorridore-Panel
   liegt ueber einem dunkleren Backdrop (rgba(0,0,0,0.55)) und rechnet sich auf
   rgb(8,84,138) herunter, was jeden Wert unten noch anhebt.
     #ffffff  Fliesstext, Feldwerte, Titel .................... 7,34:1
     #C3D3E2  Feldnamen, inaktive Reiter, Zusatz ............... 4,80:1
     #A9F6DB  Mint-Kante, aktiver Reiterbalken, Fokusring ...... 5,90:1
     #07203a  CTA-Schrift auf Mint-Grund #A9F6DB .............. 13,23:1
     rgba(255,255,255,0.82) Filter-Panel-Beschriftungen (N3) ... 5,51:1
   Hell (Panelgrund #ffffff):
     #0b2035  Fliesstext ..................................... 16,50:1
     #3C4F5E  Feldnamen, inaktive Reiter ....................... 8,50:1
     #00528D  aktiver Reiter, Balken, CTA-Grund ................ 8,10:1
     #0070C0  Fokusring ........................................ 5,15:1
   Alle Textwerte >= 4,5:1, alle Nicht-Text-Marken >= 3:1.

   --------------------------------------------------------------------------
   POLITUR 16, DRITTER SATZ, 12.09.2026, ?v=24 (Anwender-Entscheid F3 nach dem Live-VRT).
   Abschnitt 2b: mobile Kurzfassung des Intro-Absatzes - .zk-intro-klein (display: none)
   erscheint unterhalb 48em an Stelle von .zk-intro-gross (Girokonto-Muster). Anlass:
   bei 375 x 800 stand mit der langen Fassung kein Band mehr im ersten Bildschirm
   (VRT-Befund B1: Buehnenoberkante 900,75 px, sichtbares Band 0 statt 49,5 px).

   --------------------------------------------------------------------------
   POLITUR 16, 12.09.2026, ?v=23 (E70-E72, Anwender-Auftrag). Zwei Stellen:
     - E70 KURZERKLAERUNG ueber dem Diagramm: #vergleich .zk-intro (Abschnitt 2b) samt
       Hell-Pendant, zeichengleich zur Festgeld-Regel #vergleich .zg-intro (margin
       0.24rem 0 0.96rem, max-width 44em, 0.96rem/1.4, weiss; hell #003A66). Gemessen
       12.09.2026 an der Zielstelle (vor .results-header, Live 1200 px): Grund ist das
       Body-Blau #0070C0 durch das quasi-transparente Dashboard rgba(0,0,0,0.02), der
       Trefferzaehler daneben steht in rgba(255,255,255,0.7); die Festgeld-Intro misst
       live 15,36 px Schrift, 21,5 px Zeilenhoehe, 3,84 px oben, 15,36 px unten, max
       675,84 px breit — dieselben Werte liefert die Regel hier (Root 16 px). Das
       Polster 0 5px 0 4px kommt wie bei Festgeld aus #vergleich p (Bestand).
     - E72 SCROLL-LOCK (Abschnitt 18): nur noch html.zk-overlay-locked body traegt
       overflow: hidden. Vorher stand die Deklaration auf html UND body — und weil der
       Bestand beiden height: 100% gibt (gemessen 800 px bei 800 px Viewport), wurde
       body zum geklemmten Container, html.scrollHeight fiel von 8671 auf 800 px und
       der Viewport sprang beim OEFFNEN des Panels auf 0 (gemessen 1440 -> 0 px, in
       allen drei Schliesswegen). Einzeln gesetzt halten html-only wie body-only die
       Position UND blockieren das Mausrad (je gemessen). body-only wie Brokerage
       (html.kb-overlay-locked body). Begruendung ausfuehrlich am Regelblock.
     - Die Sortier-Begriffe (E71) sind reines Core-Markup; die Kommentare in Abschnitt
       14 und 16b nennen die alten Woerter ("Bestzins", "Spannenbreite") als Historie.

   --------------------------------------------------------------------------
   AKTIVIERUNG (POLITUR 15), 12.09.2026, ?v=22 (E69, Anwender-Auftrag). Abschnitt 9:
     - ANSICHTS-GLYPHE .zk-view-icon auf die Blaupause der Schwesterprodukte
       (zg-/kb-view-icon): display block, margin: 0 auto, width 1.3em, font-size
       1.85em mit 88em-Stufe 1.3em und 72em-Stufe 1.2em (position relative, margin 0),
       svg 1.3em x 0.91em. Das <i> traegt im Core zusaetzlich die Klasse "icon" —
       Farbe kommt seither aus den zentralen .icon-Regeln (Ruhe Mint, Hover heller,
       aktiv #104266, kontrast-hell #00528D bzw. aktiv #003A66); die eigene
       Farbdeklaration und die kontrast-hell-Regel dieses Abschnitts entfallen.
     - Gemessen 12.09.2026 (Injektion auf der Live-Seite, 1200/1366/1420/1500/1920):
       Glyphenmitte 0,01 px neben der Mitte des Zellen-Inhaltskastens (vorher
       15,76 px links der Zellenmitte bei 1200 px), Glyphe 25,95 x 20,53 px bei
       1200 px (vorher 19,19 x 13,44). Die Filter-Knopf-Konstanten der Icon-Zeile
       im Core wechseln deshalb von Gruppe C auf Gruppe A.
     - Unterhalb 72em greift die neue Stufe ebenfalls (font-size 1.2em, position
       relative, margin 0; Glyphe bei 640 px 23,95 x 18,73 statt 19,19 x 13,44) - nur die
       LAGE bleibt dort unveraendert, weil die Flex-Zelle zentriert (gemessen 0,00 px
       vorher wie nachher). Die uebrigen Abschnitte sind nicht angefasst.
     - NACHTRAG (Smoke-Befund B1): im Band 72.01-88em zusaetzlich padding-top 0.28em an
       der Glyphe. Die Fontello-Nachbarn erben dort line-height 26,11 px als Laenge, der
       zk-Kasten mit line-height 1 misst 20,53 px - die Tinte sass 5,25 px hoeher als die
       der Nachbarn (1200 px), oberhalb 88em nicht (beide Kaesten 28,42 px). Nach dem
       Polster Kastenhoehe 26,11 px, Glyphenmitte 0,55 px ueber der Nachbar-Kastenmitte
       (oberhalb 88em: 0,71 px). Die Schwesterprodukte tragen denselben Versatz
       (Blaupause) - Ticket fuer den Rollout.

   --------------------------------------------------------------------------
   POLITUR 14, 12.09.2026, ?v=21 (E68, Anwender-Auftrag). Eine Regel in Abschnitt 6 und
   ihr Hell-Pendant in Abschnitt 17:
     - BANNER "FESTZINS" (.zk-badge-festzins) in p.zk-zeile-werte der Zeilen mit
       festzins === true, an Stelle der Beschriftung "fester effektiver Jahreszins:".
       Optik zeichengleich zum Festzins-Badge der Listen-/Tabellenansicht: Mint #A9F6DB
       auf neutral abdunkelnder Fuellung rgba(0,0,0,0.26) mit Mint-Kontur 0.5, 0.68rem,
       Gewicht 600, Radius 0.25em (dunkel 14,4:1 rechnerisch); hell wie die Liste
       #00528D auf rgba(0,112,192,0.10) (6,7:1 rechnerisch ueber #F7F9FC). Auf der
       Grundlinie des Zinssatzes, line-height 1.2 wie die Tabellen-Pille im Card-Modus;
       die Wertezeile einer Festzins-Zeile waechst damit um weniger als 1 px (0,97 px
       im Bau-Smoke mit 1-px-Rahmen, 0,31 px in der Review-Umgebung mit 0,54-px-Rahmen),
       bewusst hingenommen — Begruendung am Regelblock in Abschnitt 6.
       Kein Banner "bonitaetsabhaengig" (Anwender-Entscheid: die Spanne zeigt es).
       Markup und aria-label kommen aus dem Core; Engine unveraendert (?v=15).

   --------------------------------------------------------------------------
   POLITUR 13, 12.09.2026, ?v=20 (E66, Anwender-Auftrag). Neuer Abschnitt 16b und
   zwei Palettenwerte:

     - DAUERHAFTE MARKE der linken Endkappe unter der Sortierung "Bestzins"
       (.zk-buehne[data-sortbasis="zins"] .zk-band .zk-cap-lo): Knopf statt Strich —
       0.36rem statt 0.14rem breit, rund, mit 0.1rem Kontur in Buehnenfarbe. Keine
       neue Farbe (--zk-cap bleibt), zwei Formmerkmale (P§8), unterscheidbar von der
       Randlagen-Kappe .zk-cap-kante (die ist hoeher; unter Bestzins hoeher UND
       Knopf). Nur an Baendern — Punkt und Festzins haben kein linkes Ende. Gilt
       fuer zins_asc und zins_desc: die Basis ist der Bestzins, die Richtung
       aendert das Merkmal nicht.
     - PULS nach einem Sortierklick auf dem Sortiermerkmal je Basis (Anbietername /
       linke Endkappe + Punkt / Raute + Punkt / Band + Punkt): ein outline-Ring, der sich
       loest und verblasst, beim Anbieternamen eine verblassende Flaeche. Start
       NACH der FLIP-Bewegung (animation-delay var(--zk-flip-dauer)), sichtbare Dauer
       --zk-puls-dauer 1100 ms, unter prefers-reduced-motion dieselben Marken OHNE
       Bewegung (nur Farbe verblasst). Ausloeser ist data-sortpuls der Engine
       (?v=15); der Core kennt dieses Attribut nicht, data-sortbasis dagegen setzen
       Core UND Engine.
     - Paletten (Abschnitt 1): --zk-puls-ring (#ffffff / hell #0b2035) und
       --zk-puls-flaeche (rgba(255,255,255,0.22) / hell rgba(0,82,141,0.15)).
       Weiss bzw. Textdunkel, weil Mint, Blau, Violett und Apricot semantisch belegt
       sind. Weisser Anbietername auf der Startflaeche gegen die Buehne: gemischt
       rgb(62,81,101), 8,2:1; hell #0b2035 auf gemischt rgb(210,224,235), 12,3:1 —
       beides rechnerisch, die Browser-Messung (8,17:1 / 12,26:1, identisch) steht im
       Bau-Bericht memory\berichte\politur13-2026-09-12-bau.md.
     - Panel, Reiter "alle Zinssaetze" (E65): die Kopfzeile "bei Nettodarlehensbetrag
       EUR … bis EUR …" traegt die Zweitklasse .zk-feld-satz — der Feldname nimmt
       seine natuerliche Breite statt der 10rem-Spalte (Abschnitt 20, Inhalt der
       Flaechen), sonst braeche er in zwei Zeilen um (gemessen 36,19 px statt 19,03 px).
     - Die uebrigen Textaenderungen (E65) betreffen nur den Core; die laengere
       Zeile .zk-zeile-repr ("laut Kreditbeispiel … bei Nettodarlehensbetrag … und
       Laufzeit …") umbricht in der 17rem-Labelspalte eine Zeile mehr — die
       Zeilenhoehe waechst, FLIP misst Positionen und ist davon unberuehrt.

   ZUM BUMP: Gemessen am 12.09.2026 liefert der Server diese Datei unter ?v=19
   (Live = Upload = Projekt); diese Datei geht auf 20, die Core-Referenz zieht nach.
   Die Engine geht im selben Satz auf ?v=15 (data-sortbasis-Nachfuehrung + Puls).

   --------------------------------------------------------------------------
   POLITUR 12, DRITTER SATZ, 10.09.2026, ?v=19 (E64). Wieder EINE Regel und ihr
   Hell-Pendant, auf Anwender-Auftrag nach der Live-Abnahme des ?v=18-Satzes:

     - E64 .zk-zinsmatrix-zeile[aria-current] VERLIERT DEN BALKEN LINKS. Sie war nach
       E62/E63 die letzte Stelle des Produkts mit gruenem Balken links (als
       inset-box-shadow gebaut). Die Bedeutungskollision haengt an der Farbe, nicht am
       Untergrund — der Anwender hat sie deshalb ebenfalls nachgezogen, obwohl sie
       eine Auswahl in einer Datenmatrix markiert und keine Fundstelle.
     - DIE FLAECHE BLEIBT, in beiden Paletten. Sie liegt auf dem dunklen Panelgrund,
       wo Mint gemessen traegt: 40,0 % relativer Luminanzsprung am Nachbarelement
       .zk-repr-hinweis gegen 23,2 % derselben Farbe auf dem hellen Seitengrund
       (Live-VRT und Review, 10.09.2026). Deshalb kein dunkler Ton wie in der
       Ergebnisuebersicht.
     - P§8 GEPRUEFT, NICHT ANGENOMMEN: es bleiben zwei nicht-farbliche Merkmale
       (Grundflaeche vorhanden/nicht vorhanden, fetter Zinswert) plus der sichtbare
       Klartext "(gewaehlte Laufzeit)" im Core-Markup, der an keiner CSS-Regel haengt.
     - NICHT angefasst: das linke Polster 0.55rem ALLER Zeilen. Es war der Platz fuer
       den Balken, traegt aber einen zweiten Zweck — laege es allein an der markierten
       Zeile, verloeren die Zinswerte ihre gemeinsame Kante.

   ZUM BUMP: Der Satz ?v=18 ist hochgeladen; damit ist die Zahl verbrannt. Diese Datei
   geht auf 19, die Core-Referenz zieht nach. Die Engine bleibt bei ?v=14.

   --------------------------------------------------------------------------
   POLITUR 12, ZWEITER SATZ, 10.09.2026, ?v=18 (E63). Nachtrag auf Anwender-Auftrag,
   nachdem der Satz ?v=17 HOCHGELADEN war (die Live-Abnahme lief zu diesem Zeitpunkt
   noch — was den Bump rechtfertigt, ist allein der Upload: mit ihm ist die Zahl
   verbrannt, unabhaengig vom Ausgang der Abnahme). EINE Regel und ihr Hell-Pendant:

     - E63 .zk-beispiel-hervor VERLIERT DEN MINT-BALKEN. Nach dem ?v=17-Satz war sie
       die einzige Stelle der Ansicht, die noch einen gruenen Balken links zeigte
       (als inset-box-shadow gebaut, nicht als border-left). Der Anwender hat sie
       ausdruecklich nachgezogen: die Bedeutungskollision "gruener Balken = positive
       Kurzmeldung" trifft eine Sprungziel-Marke genauso wie ein Hinweisfeld.
     - FLAECHE DUNKEL, dunkle Palette: rgba(169,246,219,0.12) -> rgba(4,26,45,0.25).
       Mint trug dort 28,2 % relativen Luminanzsprung und 4,28:1 Textkontrast — UNTER
       AA. Neu 36,2 % und 7,29:1. Dieselbe Rechnung und dasselbe Ergebnis wie bei E62.

       ZAHLENBASIS, nachgezogen auf Review-Befund B2 des zweiten Satzes: Der Grund ist
       NICHT der reine Seitengrund #0070C0. Zwischen Seite und Pflichtblock liegt
       div.vergleich-dashboard mit rgba(0,0,0,0.02); der wirksame Grund ist der
       zusammengesetzte Stapel rgb(0, 109,76, 188,16). Gegen ihn gerechnet (und vom
       VRT am gerenderten Pixel bestaetigt): Mint 0.08 -> 18,2 % / 4,68:1 ·
       Mint 0.10 -> 23,2 % / 4,54:1 · Mint 0.12 -> 28,2 % / 4,39:1 ·
       Mint 0.14 -> 33,5 % / 4,26:1 · Mint 0.18 -> 44,5 % / 3,99:1 ·
       dunkel 0.25 -> 36,2 % / 7,29:1. Der Stapel selbst traegt 5,32:1.
       WER FLAECHENKONTRAST MISST, KOMPONIERT DIE GANZE ELTERNKETTE — halbtransparente
       Zwischenlagen sind hier der Regelfall, nicht die Ausnahme.
     - HELL nur der Balken weg, Flaeche unveraendert: rgba(0,112,192,0.10) auf Weiss
       traegt 13,4 % Sprung bei dunklem Text.
     - KEIN Polster ergaenzt: die Pflichtliste laeuft per FLIP: eine Layout-Aenderung
       waehrend des Laufs verschoebe die gemessenen Positionen. Deshalb war der Balken
       nie ein Rahmen.

   ZUM BUMP: Der Satz ?v=17 ist hochgeladen; mit dem Upload ist die Zahl verbrannt —
   das allein traegt den Bump. Diese Datei geht deshalb auf 18, die Core-Referenz zieht nach.
   Die Engine ist erneut nicht beteiligt und bleibt bei ?v=14.

   --------------------------------------------------------------------------
   POLITUR 12, 10.09.2026, ?v=17 (E62). Kleiner Patch, kein Phasen-Bau. Vier
   Hinweisfelder in zwei Bereichen — zwei in der Ergebnisuebersicht
   (.zk-modushinweis, .zk-fussnote), zwei im Detailpanel (.zk-repr-hinweis,
   .zk-panel-hinweis) — plus ihre drei Hell-Pendants. Leiter, Achse, Band, Raute,
   Median, Legende, Pflichtblock, Sortierleiste, Panel-Geometrie und die
   FLIP-Grundlagen sind NICHT angefasst; die Engine aendert sich nicht.

   ZUM BUMP: Gemessen am 10.09.2026 lieferte der Server diese Datei unter ?v=16
   aus, die Engine unter ?v=14. Diese Datei geht auf 17, die Engine bleibt bei 14
   und behaelt ihren version-Export '14' — der Lockstep ist seit CT-0229
   aufgeloest, gebumpt wird, was sich aendert. Wer die geltende Zahl braucht:
   messen, nicht abschreiben (Befehl im Kasten am Ende dieses Kopfes).

     - E62 KEINE MINT-KANTE AN HINWEISFELDERN. Alle vier Felder verlieren ihr
       border-left: 0.1875rem solid #A9F6DB, die Hell-Pendants ihr
       border-left-color: #00528D. Die hinterlegte Flaeche traegt die
       Hervorhebung ab jetzt allein. Grund ist keine Optik-Praeferenz, sondern
       eine Bedeutungskollision: der gruene Balken links ist im Haus die Marke
       der POSITIVEN Kurzmeldung. Ein Herkunfts- oder Modushinweis ist weder
       positiv noch negativ — er faerbte hier eine Wertung ein, die der Text
       nicht trifft.
     - E62 FLAECHE DER BEIDEN UEBERSICHTS-FELDER DUNKEL STATT MINT
       (rgba(169,246,219,0.10) bzw. 0.08 -> rgba(4,26,45,0.25)). Anwender-Entscheid
       nach der Messung: ohne Kante setzte die Mint-Flaeche auf dem Seitengrund
       #0070C0 gar nicht ab (Luminanzsprung 23,2 % bzw. 18,2 % relativ zum Grund),
       und mehr Mint-Deckkraft haette den weissen Text unter AA gedrueckt
       (0.14 -> 4,26:1, 0.18 -> 3,99:1). Der dunkle Ton setzt mit 36,2 % ab und hebt
       den Kontrast auf 7,29:1 (VRT am gerenderten Pixel: 36,3 % und 7,28:1).
       MASSSTAB IST DER RELATIVE Sprung: die Panel-Felder tragen ihr Mint mit 35,8 %
       gegen den dunkleren Panelgrund und bleiben deshalb unveraendert — gleiches
       absolutes Delta-L, andere Antwort (Review-Befund B1).
     - E62 KONTRAST-GEWINN, kein behobener AA-Verstoss: der Text lag auf der alten
       Mint-Flaeche bei 4,54:1 (.zk-modushinweis) bzw. 4,68:1 (.zk-fussnote) — knapp
       UEBER der AA-Schwelle 4,5:1, nicht darunter. Die erste Fassung dieses Blocks
       behauptete 4,43:1 und einen AA-Verstoss; sie rechnete gegen den reinen
       Seitengrund und uebersah die 2-%-Schwarzlage der .vergleich-dashboard
       (Review-Befund B2 des zweiten Satzes). Beide Felder messen jetzt 7,29:1. UNTER
       AA lag allein .zk-beispiel-hervor mit 4,39:1 — behoben mit E63. Die HELLE Palette bleibt
       unveraendert: dort traegt rgba(0,82,141,0.06/0.08) auf Weiss schon mit
       Delta-L 0,094 bzw. 0,128 bei ueber 10:1 Textkontrast. Die beiden
       PANEL-Felder behalten ihr Mint — sie liegen auf dem dunklen Panelgrund.
     - E62 POLSTER +0.3em OBEN UND UNTEN, alle vier Felder. Die Kante war auch
       ein optischer Halt; der wandert nach innen. .zk-modushinweis
       0.6em -> 0.9em, .zk-fussnote 0.7em -> 1em (beide bereits em-basiert),
       .zk-repr-hinweis 0.5rem -> calc(0.5rem + 0.3em), .zk-panel-hinweis
       0.8rem -> calc(0.8rem + 0.3em). Das calc() ist kein Schmuck: die Datei
       fuehrt im Panel eine rem-Metrik, der Zuwachs soll aber am Schriftgrad des
       jeweiligen Absatzes haengen. Ausgerechnet ergibt das im Panel
       0.5rem + 0.225rem (repr, 0.75rem Schriftgrad) bzw.
       0.8rem + 0.255rem (panel-hinweis, 0.85rem) — beides Werte, die beim
       naechsten Schriftgrad-Eingriff von selbst mitziehen.
     - E62 AUSSENABSTAND +1em OBEN UND UNTEN, NUR IM PANEL. .zk-repr-hinweis
       margin 0 0 0.7rem -> 1em 0 calc(0.7rem + 1em), .zk-panel-hinweis
       margin 0 -> 1em 0. Die beiden Felder der Ergebnisuebersicht behalten ihre
       Margen: dort steht das Feld ohnehin frei zwischen Bloecken, im Panel
       dagegen zwischen Feldliste und Beispieltext.
     - E62 DREI SELEKTOREN UM #vergleich ERWEITERT — und das ist der eigentliche
       Befund dieses Satzes. Die Vorabmessung (Route-Ersetzung, CDP-Kaskade,
       10.09.2026) zeigte: das Polster der drei p-Hinweisfelder war seit ihrer
       Einfuehrung TOT. style.css fuehrt #vergleich p { padding: 0 5px 0 4px;
       line-height: 1.4em } mit (1,0,1) und schlug damit sowohl .zk-modushinweis
       (0,1,0) als auch die beiden Panel-Regeln (0,3,0). Gerendert standen dort
       0 px oben und unten, 4 px links, 5 px rechts — waehrend die Datei
       0.5rem/0.7rem behauptete. Die margin-Werte griffen, weil der Bestand an
       dieser Stelle keine setzt; genau daran war der Fehler unsichtbar.
       Mit #vergleich davor tragen die Selektoren (1,1,0) bzw. (1,3,0) und
       gewinnen. Kein !important. Die Hell-Pendants stehen mit (1,2,0)/(1,4,0)
       weiter darueber, der Leak-Reset .zk-panel-overlay .zk-panel p (0,2,1)
       weiter darunter — beides geprueft.
     - MITGEZOGENE NEBENWIRKUNG, gemessen und gewollt: mit dem padding wird auch
       die line-height dieser drei Regeln erstmals wirksam (1.4em -> 1.5). Am
       .zk-repr-hinweis der 60-Monate-Seite: Zeilenabstand 16,8 px -> 18 px,
       Blockhoehe 83,98 px -> 113,19 px. Wer den Block wieder kompakter will,
       aendert die line-height der Regel — nicht ihre Spezifizitaet.
     - .zk-fussnote braucht die Erweiterung NICHT: sie ist ein div, #vergleich p
       trifft sie nicht, ihre Werte griffen immer (gemessen 10,75 px -> 15,36 px
       Polster). Ihr eigener p-Reset gilt nur den Kindabsaetzen.
     - GEMESSENE ENDWERTE (Live-Layout, Route-Ersetzung, 1400 px, beide
       Paletten identisch): Kante ueberall 0 px. Polster oben/unten
       .zk-fussnote 15,36 · .zk-modushinweis 12,24 · .zk-repr-hinweis 11,60 ·
       .zk-panel-hinweis 16,88. Aussenabstand oben/unten im Panel
       .zk-repr-hinweis 12,00/23,20 · .zk-panel-hinweis 13,60/13,60.
     - E45 IST NICHT BERUEHRT. Er bindet den WORTLAUT der § 17-Fussnote und des
       Pflichtblocks, nicht ihre Flaechenoptik. Kein Textzeichen dieses Satzes
       hat sich geaendert; der Pflichtblock selbst ist gar nicht angefasst, und
       die Kennzeichnung des gewaehlten Eintrags (.zk-beispiel-hervor, inset
       box-shadow statt Rahmen) bleibt bewusst stehen — sie markiert eine Zeile,
       sie hinterlegt keinen Hinweis. [MIT E63 UEBERHOLT: der Anwender hat sie im
       zweiten Satz ?v=18 nachgezogen, siehe dessen Block weiter oben.]

   --------------------------------------------------------------------------
   POLITUR 11, 10.09.2026, ?v=16 (E57-E61, CT-0349). Kleiner Patch, kein
   Phasen-Bau. Wieder nur Abschnitt 20 (Detailpanel) und sein Hell-Pendant in
   Abschnitt 21; Leiter, Achse, Band, Raute, Median, Legende, Pflichtblock,
   Sortierleiste und die FLIP-Grundlagen sind NICHT angefasst.

   ZUM BUMP: Gemessen am 10.09.2026 lieferte der Server diese Datei unter ?v=15
   aus. Sie geht damit auf 16, die Core-Referenz laeuft auf ?v=16. Ob die Engine
   in diesem Satz mitbumpt, entscheidet ihr eigener Diff (Teil F der Politur
   beruehrt sie) — der Lockstep ist seit CT-0229 aufgeloest, gebumpt wird, was
   sich aendert. Wer die geltende Zahl braucht: messen, nicht abschreiben.

     - E57 SCHLIESSKNOPF, FESTGELD-PARITAET. Die Media-Regel des ?v=15-Satzes fuer
       das Band 48em < Breite <= 52em ist ENTFALLEN; oberhalb 48em gilt jetzt
       durchgehend die 2.4rem der Basisregel (38,4 px) wie .zg-karte-close, das
       Sheet <= 48em behaelt 2.75rem (44 px). Anwender-Entscheid vom 10.09.2026
       nach dem Upload: Vorbild-Paritaet schlaegt das Core-Touch-Mass. Die
       Core-INLINE-Regel .panel-close-btn setzt im Band weiter 2.75rem, ist aber
       nicht diese Datei und verliert mit 0,1,0 gegen die 0,3,0 der Basisregel.
     - E58 BESCHRIFTUNG UEBER DEM BEISPIELTEXT. Neue Klasse .zk-beispiel-titel
       ("Repraesentatives Beispiel (§ 17 PAngV)") in Feldnamen-Optik: 0.78rem /
       1.45 / #C3D3E2, hell #3C4F5E, 0.2rem Abstand nach unten. Markup im Core
       (<p> direkt vor p.zk-beispieltext), kein <h3>. Der Selektor traegt 0,3,0,
       weil der Leak-Reset .zk-panel-overlay .zk-panel p (0,2,1) sonst margin und
       Schriftgrad toetete — Falle des ?v=12-Satzes, vorab geprueft.
     - E59 SPRUNGLINK IN DEN FLAECHEN (Nachtrag nach dem Smoke: untere Marge 0.6rem am
       Link in den Flaechen, damit er im Scroll-Fall nicht auf der Trennlinie steht --
       gemessen 0,34 px, vorher 9,6 px ueber die Feldlisten-Marge). .zk-detail-sprung steht nicht mehr im
       .zk-detail-fuss, sondern als letztes Kind in den Reiterflaechen
       "zinssaetze" und "merkmale" (Markup im Core). Die REGEL ist unveraendert —
       Farbe, Unterstreichung, Fokusring und margin-top 0.5rem tragen dort
       gemessen sauber; nur die Kommentare an .zk-detail-sprung und
       .zk-detail-zusatz sind nachgezogen (Fuss = Zusatz -> CTA).
     - E60 FUSSFREIRAUM +1.5em (A2). .zk-detail-fuss padding-top: 0.75rem ->
       calc(0.75rem + 1.5em). Der Freiraum sitzt damit ZWISCHEN Trennlinie und
       erstem Fusskind, nicht vor der Linie — Anwender-Entscheid; die Linie bleibt
       dicht am Flaecheninhalt. em-Basis ist der Fussschriftgrad (erbt 0.9rem =
       14,4 px), Zuwachs 21,6 px, Summe 33,6 px. Der 48em-Block setzt am Fuss kein
       eigenes padding-top, der Freiraum gilt im Sheet unveraendert mit.
     - E61 (Spannen-Tiebreaker) beruehrt diese Datei NICHT — er sitzt in der
       Filter-Pipeline und in der Engine.

   --------------------------------------------------------------------------
   POLITUR 10.09.2026, ?v=15 (E52-E56). Kleiner Patch, kein Phasen-Bau. Der
   Schwerpunkt liegt in Abschnitt 20 (Detailpanel); Leiter, Achse, Band, Raute,
   Median, Palette, Legende, Pflichtblock und die FLIP-Grundlagen (Abschnitt 16)
   sind NICHT angefasst.

   ZUM BUMP: Gemessen am 10.09.2026 lieferte der Server CSS unter ?v=14 aus, die
   Engine unter ?v=13. Der Lockstep CSS+JS ist seit CT-0229 aufgeloest — gebumpt
   wird nur, was sich aendert. Diese Datei geht also auf 15, die Engine bleibt bei
   13 und behaelt ihren version-Export '13'; sie aendert sich in diesem Satz nicht.
   Wer die geltende Zahl braucht: messen, nicht abschreiben (Befehl im Kasten am
   Ende dieses Kopfes) — genau daraus entstanden B10, B11 und B12.

     - E53 PANEL-GEOMETRIE. Das Detailpanel ist am Desktop (> 48em) kein
       zentriertes Fenster mehr, sondern ein RECHTS EINFAHRENDES SEITENPANEL in
       der Geometrie von .zg-karte (Festgeld DE): 30rem breit, volle
       Viewport-Hoehe, Kopfzone 4.65em, Glas mit Mint-Kante links, Schatten nach
       links, 0.9rem/1.35 Grundschrift. Das Overlay verliert dafuer sein
       Flex-Zentrieren und sein 2rem/1rem-Aussenpolster (display: block,
       padding: 0); das Panel dockt sich selbst per position: absolute an. Die
       Einblendung schiebt jetzt von rechts (translateX(100%) -> none, 280ms
       cubic-bezier(0.22, 0.61, 0.36, 1)) statt von oben einzuschweben, der
       opacity-Anteil des Desktop-Keyframes entfaellt. Backdrop-Fade bleibt und
       zieht auf dieselbe Dauer mit; das reduced-motion-Pendant bleibt
       inhaltlich unveraendert.
     - BACKDROP-FARBE rgba(9, 30, 48, 0.5), hell rgba(0, 26, 48, 0.35). Der
       Wert kommt NICHT vom Vorbild — das Festgeld-Panel ist hover-basiert,
       nicht-modal und hat gar keinen Backdrop. Er kommt von den modalen
       Haus-Schwestern Tagesgeld-DE-Skyline und Brokerage-Kurvenblick, weil
       dieses Panel modal bleibt (aria-modal, Fokusfalle, Esc, Scroll-Lock). Der
       bisherige Neutralwert rgba(0,0,0,0.55) war ein Eigenweg ohne Vorbild.
     - FUSS-ANKER. .zk-panel-body wird selbst eine Flex-Spalte, .zk-detail fuellt
       sie (flex: 1 0 auto), .zk-detail-fuss haengt per margin-top: auto am
       unteren Ende. Bei kurzem Inhalt steht der CTA damit am Panel-Ende, bei
       langem folgt er dem Inhalt im Scroll.
     - E56 SCHLIESSKNOPF. Er wird ab jetzt HIER gestaltet und nicht mehr im
       Inline-Block des Cores: der Knopf des Detailpanels traegt die Zweitklasse
       .zk-panel-close, der Selektor .zk-panel-overlay .zk-panel .zk-panel-close
       traegt 0,3,0 und schlaegt Core-Inline-Regel wie zentrale Regel (je 0,1,0).
       Der Knopf des FILTER-Panels traegt die Zweitklasse nicht und bleibt
       unberuehrt. Werte 1:1 aus .zg-karte-close, Sheet-Mass 2.75rem. [UEBERSTIMMT
       IN ?v=16, E57 — der folgende Satz beschreibt einen Stand, den es nicht mehr
       gibt:] Im Band 48em < Breite <= 52em haelt eine eigene Media-Regel die
       2.75rem des Core-Touch-Masses (Review B1 + Codex B1, gemessen 800 px =
       44 px, 840 px = 38,4 px) — bewusste Abweichung von der Festgeld-Paritaet in
       genau diesem Band.
     - E56 CTA UND PFEIL-CHIP. .zk-detail-cta uebernimmt die Optik von
       .zg-dk-cta (inline-flex, align-self: flex-end, 0.8em/1.3em, 1rem, Radius
       0.5rem, Uebergang 150ms), der Chip .link-arrow die des Listen-Chips in
       em-Fassung. Farben als LITERALE: das Panel liegt ausserhalb der
       .vergleich-dashboard, wo die Bestandsvariablen definiert sind. Das globale
       a::after-Icon wird unterdrueckt — die einzige !important-Stelle des
       Abschnitts, Haus-Muster von Liste, Festgeld und Tagesgeld.
     - FUSS-REIHENFOLGE Zusatz -> Sprung -> CTA (Markup im Core). Der Fuss wird
       eine Spalte mit align-items: flex-start; die Margins ziehen nach:
       Zusatz 0, Sprung 0.5rem oben, CTA 0.9rem oben und rechtsbuendig.
     - HELL-PENDANTS (Abschnitt 21): Panel #F7F9FC ohne Weichzeichner,
       Kante #00528D, Text #22303c; Knopf rgba(0,82,141,0.12)/#003A66 mit Hover
       0.22 und Fokusring #00528D; CTA #0070C0/weiss mit Hover #00528D — die
       Richtung ist gegen frueher gedreht (vorher #00528D mit #0070C0 als
       Hover), sie folgt jetzt dem Listen-Kontrast; Chip #F7F9FC/#00528D;
       Sheet-Kante #00528D. Die bestehenden Hell-Regeln fuer Titel, Reiter,
       Felder und Zinsmatrix bleiben unveraendert.
     - EIN BEFUND DER VORABMESSUNG, mitbehoben: der helle Schatten zeigte nach
       UNTEN (0 0.5em 2.5em / 0 0.125em 0.5em) — richtig fuer das zentrierte
       Fenster von vorher, wirkungslos an einem rechts angedockten Panel und
       unter einem Bottom-Sheet, wo er hinter die Viewport-Kante faellt. Die
       Staerke des hellen Satzes bleibt, die Achse dreht mit der Geometrie:
       Desktop nach links, Sheet nach oben (eigene Regel im 48em-Block des
       Hell-Abschnitts). Gemessen 10.09.2026 an der Live-Seite mit ersetzter
       Stylesheet-Antwort.
     - Gerechnete Kontraste der neuen Farbpaare: CTA #004578 auf #A9F6DB
       7,96:1 · Chip #ffffff auf #004578 9,90:1 · Knopfglyph #ffffff auf dem
       gemischten Knopfgrund 5,07:1 · hell: CTA weiss auf #0070C0 5,15:1 ·
       Chip #F7F9FC auf #00528D 7,68:1 · Knopf #003A66 auf gemischtem Grund
       9,07:1 · Panel-Text #22303c auf #F7F9FC 12,79:1.
     - NICHT IN DIESER DATEI: E52 (Reihenfolge der Sortier-Segmente) und E54
       (drei statt fuenf Reiter) sind reine PHP-Array-Aenderungen. Abschnitt 14
       steuert die Segmente ueber data-basis, nicht ueber ihre Position; die
       Reiter-Regeln gelten je Reiter, nicht je Anzahl. Hier war deshalb nichts
       nachzuziehen — nur ein Kommentar am Panel-Body, der "fuenf Reiter" sagte.
       "Reiter 2" am Zinsmatrix-Block bleibt richtig: die Zinssaetze sind auch
       unter E54 die zweite von drei Flaechen.

   --------------------------------------------------------------------------
   VIERTER SATZ ?v=12 (06.08.2026) — Nachbesserung, eine Zeile:

     Der margin des neuen .zk-legende-auswahl war TOT. Weiter unten in dieser Datei
     steht .zinskorridore-dashboard .zk-legende p { margin: 0 } mit Spezifitaet
     (0,2,1); die kurze Fassung .zk-legende-auswahl (0,1,0) verliert dagegen. Live
     gemessen: margin-top 0px, Abstand zur Eintragsliste 0,00 px — der Absatz klebte
     an der Liste. Mit dem voll qualifizierten Selektor 11,2 px.
     GEFUNDEN wurde das erst NACH dem Upload, weil die Vorab-Messung des dritten
     Satzes die INJIZIERTE Regel geprueft hat (die im <head> steht und damit spaeter
     kaskadiert) statt der ausgelieferten. Injiziert ist nicht ausgeliefert.
     BESTANDSBEFUND aus derselben Messung, NICHT behoben (kein Auftrag, sichtbare
     Optik-Aenderung): dieselbe p-Regel toetet auch .zk-legende-titel
     (margin-bottom: 0.5rem, gemessen 0px) und aller Wahrscheinlichkeit nach
     .zk-legende-modus (0.6rem; im Messstand nicht gerendert, erscheint nur bei
     bonitaet=nein).

   --------------------------------------------------------------------------
   DRITTER SATZ ?v=11 (06.08.2026) — zwei Punkte. Zweiter zuerst, weil kurz:

     .zk-legende-auswahl — neue Regel fuer den Erklaerungsabsatz unter der
     Eintragsliste (Anwender-Auftrag): wonach die Zeilen ausgewaehlt sind.
     Zeichengleich zu .zk-legende-modus, Abstand oben statt unten.

   Und der eigentliche Befund:

     box-sizing: border-box fuer die MARKEN der Legende (Punkt, Raute, Konflikt,
     Randlage). Der globale border-box-Reset des Projekts erfasst PSEUDOELEMENTE
     nicht — gemessen: ein frisch eingefuegtes <div> meldet border-box, sein ::after
     content-box. Dieselbe Zentrierung traf deshalb in der Leiter (echtes Element)
     die Mitte und in der Legende (Pseudoelement) nicht. Begruendung und Messwerte
     stehen am Regelblock in Abschnitt 10.
     Vorher/nachher live gemessen: Randlage +2,153 -> -0,004 px, Raute und Konflikt
     +1,075 -> -0,004, Punkt +1,614 -> -0,004; das rahmenlose Band als Kontrollprobe
     unveraendert 0,000. Nebenwirkung und Gewinn zugleich: die drei Rauten-Proben
     messen jetzt 12,7921 px Aussengroesse — exakt die der Raute in der Leiter, die
     vorher um zweimal die Rahmenbreite kleiner war als ihre eigene Legende.

   --------------------------------------------------------------------------
   POLITUR 06.08.2026 (Anwender-Entscheid, drei Punkte). Kein Phasen-Bau, ein
   kleiner Patch — aber mit Lockstep-Bump, weil CSS UND Engine sich aendern. Die
   ausgelieferte Version war vorher gemessen ?v=8 (Befehl im Kasten unten), der
   Satz ging als ?v=9 heraus.

   ZWEITER BUMP auf ?v=10 am selben Tag: Der version-Export der Engine war beim
   ersten Satz auf '8' stehengeblieben, das Live-Gate (34) hat es gemeldet. Mit dem
   Upload war die 9 verbrannt (max-age 604800), also musste die Korrektur unter einer
   NEUEN Zahl heraus. DIESE DATEI aendert dabei inhaltlich nichts; sie geht nur mit,
   weil der Lockstep sie mitzieht — dieselbe Lage wie beim zweiten Bump der Phase 5.

     - RANDLAGE OHNE VERSATZ (E14 neu gefasst, Abschnitt 8 und die Legendenprobe
       in Abschnitt 10). Die Raute stand bei einem Beispielwert genau auf dem
       Bestzins um 0,72rem nach oben abgesetzt neben dem Korridor; sie steht jetzt
       auf dessen vertikaler Mitte wie in den drei anderen Lagen. Die Kennzeichnung
       tragen weiter ZWEI Formmerkmale (verstaerkte Rautenkontur, verstaerkte
       Endkappe) — P§8 "nie nur ueber Farbe" bleibt damit erfuellt.
     - ABSCHNITT 15 AUFGELOEST. Tabellen-Umschalter und die Gegenregel
       .zk-fallback--sichtbar samt Folgeregeln sind entfernt; die Textfassung hat
       keinen sichtbaren Zustand mehr. Betrifft auch drei Regeln der hellen
       Palette in Abschnitt 17 und die Fokus-Sammelregel in Abschnitt 14.
     - RANGNUMMER ALS BADGE (Abschnitt 6 und 12). .zk-rang und .zk-pflicht-rang
       tragen die Optik von .produkt-rang der Listenansicht: runde 2rem-Flaeche,
       700, heller Grund, ohne Ordnungspunkt. 2rem statt der 48px der Desktop-
       Liste, weil der Badge hier in einer 0.85rem-Textzeile ueber einem Korridor
       steht. :empty nimmt bei geteilten Plaetzen nur den GRUND zurueck, nicht die
       Flaeche — sonst rutschten die Namen der Folgezeilen einer Gruppe nach links
       aus der Flucht.

   --------------------------------------------------------------------------
   Phase 5, Bauabschnitt A (Mobile-Karten, 31.07.2026, Bump auf die naechste Zahl —
   gemessen, nicht abgeschrieben, siehe den Kasten unten). Der Schwerpunkt der
   Phase liegt in DIESER Datei:

   ZWEITER BUMP derselben Phase (Review-Befund P1): Beim ersten Upload blieb
   ratenkredit-diagramm-race.js liegen. Der Core referenzierte die neue Zahl,
   waehrend darunter noch die Engine der Vorphase lag — bei max-age=604800 haben
   Browser sieben Tage lang die alte Engine unter dem neuen Schluessel gecacht.
   Diese Datei aendert dabei INHALTLICH NICHTS; sie geht nur mit, weil der
   Lockstep sie mitzieht. "Kein zweiter Bump innerhalb derselben Aenderung" gilt
   nur, solange die Fassung nicht ausgeliefert ist — mit dem Upload erlischt die
   Ausnahme, jedes Mal neu.

     - ABSCHNITT 13 neu gefasst — DIE ZEILE WIRD ZUR KARTE (A1) und DIE ACHSE
       ENTFAELLT (P§8 woertlich). Statt der Zeile mit Trennlinie steht unter 48em
       eine Karte mit eigenem Grund, Rahmen, Radius und waagerechtem Polster.
       Das Polster ist der Grund, warum .zk-median-schicht dasselbe Polster
       traegt: sonst stuende die gestrichelte Linie um genau diesen Betrag neben
       den Baendern, die sie erklaert. Ein Wert (--zk-karte-polster) fuer beide.
     - MINI-SKALA JE KARTE (A2). Neuer Regelblock vor Abschnitt 13, sichtbar erst
       im Kartenmodus. Sie liegt als dritte Zelle im Raster der Ausloeser-Flaeche
       und damit in DERSELBEN Spalte wie .zk-spur — daran haengt ihre Ausrichtung
       (gemessen: Versatz 0,00 px und Breitendifferenz 0,00 px gegen die Spur, in
       10 von 10 Zeilen, auch nach dem Umsortieren). Eigene Klassen statt .zk-tick:
       bei der Achse steht der Teilstrich unten und die Beschriftung darueber,
       hier umgekehrt. Die Dichtestufen (-mittel/-eng) nutzen dieselben Schwellen
       wie vorher die Achse.
     - MEDIAN-MARKE (A5, VRT-Befund N2). left kommt aus --zk-median-x, das der
       Core inline setzt; nur so ist die Position im Kartenmodus per Media-Query
       zurueckzunehmen (ein Inline-left braeuchte !important). Unter 48em steht die
       Marke linksbuendig ueber der vollen Spurbreite und darf umbrechen — sie ist
       mit 256 px breiter als die Spur bei 320 px (246 px) und ragte dort um
       22,1 px heraus. Gemessen nachher: 2 Textzeilen, breiteste 202 px, NULL
       Textzeilen ausserhalb der Buehne.
     - TEXTFASSUNGS-TITEL (A4, VRT-Befund N1). Die Regel fuer <caption> ist
       entfallen, .zk-fallback-titel ist neu (sticky, left: 0). Gemessen bei
       375 px: Titelbox 359 px statt der Tabellenbreite 564 px, 4 Textzeilen,
       NULL davon ausserhalb des sichtbaren Ausschnitts.
     - SORTIERLEISTE (A7-Folge). Die Segmente brechen jetzt um (white-space:
       normal + min-width: 0); das zinsrepr-Segment ist unter 30em von der
       50%-Basis ausgenommen. Die alte Zusicherung "kein Segment breiter als
       320 px" stuetzte sich auf ein 105 px breites Label, das der
       Anwender-Entscheid durch ein rund 350 px breites ersetzt hat.

   KONTRAST IM KARTENMODUS, gerechnet gegen den ZUSAMMENGESETZTEN Kartengrund —
   nicht gegen den blanken Buehnengrund. Das ist der Bezugsgrund, auf den es hier
   ankommt: die Karte legt eine halbtransparente Toenung darueber, und jeder
   Nachweis der Phase 2 galt gegen den Grund OHNE sie.
     Normal:  Toenung rgba(255,255,255,0.10) auf #07203a -> rgb(32,54,78)
       #C3D3E2  Mini-Skala (NEU), Zinswerte, § 17-Wert, Produkt ... 8,07:1
       #ffffff  Anbietername, Sprungmarke ....................... 12,33:1
       #ffb59e  Median-Marke ..................................... 7,25:1
     Hell:    Toenung rgba(0,82,141,0.08) auf #ffffff -> rgb(235,241,246)
       #4A5C6B  Mini-Skala (NEU) ................................. 6,08:1
       #3C4F5E  Zinswerte, § 17-Wert, Produkt .................... 7,46:1
       #0b2035  Anbietername, Sprungmarke ....................... 14,50:1
       #b33e19  Median-Marke ..................................... 5,10:1
   Alle Textwerte >= 4,5:1 in BEIDEN Paletten, gemessen bei 375 und 320 px.

   ASSET-VERSION NICHT AUS DIESEM KOPF ABLESEN — MESSEN. Zweimal in Folge (B10,
   B11) stand hier eine Zahl als Tatsache, die der naechste Upload ueberholt hat,
   und zweimal wurde daraus die Anweisung abgeleitet, NICHT zu bumpen:

     curl -s https://www.modern-banking.de/diagramm-ratenkredit-60-monate.php \
       | grep -o 'ratenkredit-diagramm[a-z.-]*\(min\.css\|race\.js\)?v=[0-9]*' | sort -u

   Was das ausgibt, IST die ausgelieferte Version; der naechste Bump ist die
   naechste Zahl. "Kein zweiter Bump innerhalb derselben Aenderung" gilt NUR,
   solange die Fassung nicht ausgeliefert ist — mit dem Upload erlischt die
   Ausnahme, jedes Mal neu.
   ========================================================================== */

/* ==========================================================================
   1) PALETTEN
   Zwei Traeger: die Buehne und die Legende. Die Legende steht als Geschwister-
   element AUSSERHALB der Buehne, Custom Properties vererben aber nur nach unten —
   ohne diesen zweiten Selektor blieben ihre Farbproben ohne Werte. Bewusst
   derselbe Regelblock statt einer Kopie der Hexwerte: eine zweite Werteliste
   liefe beim naechsten Palettenwechsel auseinander.
   ========================================================================== */
.zk-buehne,
.zk-legende {
    /* Palette NORMAL (dunkle Buehne) */
    --zk-grund:            #07203a;
    --zk-typo:             #ffffff;
    --zk-typo-sek:         #C3D3E2;
    --zk-band-links:       #62b4ec;
    --zk-band-rechts:      #235f9f;
    --zk-raute-fuell:      #A9F6DB;
    --zk-raute-kontur:     #07203a;
    --zk-cap:              #8fd3ff;
    --zk-median:           #ffb59e;   /* Apricot-Zweitakzent, 9,68:1 auf #07203a */
    --zk-konflikt:         #E3B8FF;
    --zk-konflikt-kontur:  #07203a;
    --zk-achslinie:        #7C93A8;
    --zk-tick-typo:        #C3D3E2;
    --zk-rahmen:           rgba(255,255,255,0.08);
    --zk-marker-grund:     rgba(255,255,255,0.10);
    /* Politur 13 (E66): Puls des Sortiermerkmals — Ring und Textflaeche
       (Abschnitt 16b). Weiss statt einer Palettenfarbe: Mint, Blau, Violett und
       Apricot sind semantisch belegt (Raute, Cap, Konflikt, Median). */
    --zk-puls-ring:        #ffffff;
    --zk-puls-flaeche:     rgba(255,255,255,0.22);

    /* Geometrie (rem, damit Achse und Zeilen bei Zoom gemeinsam skalieren) */
    --zk-label-breite:     17rem;
    --zk-spaltenabstand:   1rem;
    --zk-bandhoehe:        0.75rem;
    --zk-punktgroesse:     0.85rem;
    --zk-rautengroesse:    0.8rem;
    --zk-median-marke:     1.5rem;
    --zk-spurhoehe:        2.4rem;
}

#vergleich.kontrast-hell .zk-buehne,
#vergleich.kontrast-hell .zk-legende {
    /* Palette KONTRAST-HELL — neu gerechnet, kein Weiss-Tausch der Normalpalette */
    --zk-grund:            #F7F9FC;
    --zk-typo:             #0b2035;
    --zk-typo-sek:         #3C4F5E;
    --zk-band-links:       #1a6aa8;
    --zk-band-rechts:      #07203a;
    --zk-raute-fuell:      #0b5c43;
    --zk-raute-kontur:     #ffffff;
    --zk-cap:              #07203a;
    --zk-median:           #b33e19;   /* dunkles Apricot-Pendant, 5,50:1 auf #F7F9FC */
    --zk-konflikt:         #5B2A86;
    --zk-konflikt-kontur:  #ffffff;
    --zk-achslinie:        #7A8A97;
    --zk-tick-typo:        #4A5C6B;
    --zk-rahmen:           rgba(0,82,141,0.20);
    --zk-marker-grund:     rgba(0,82,141,0.08);
    --zk-puls-ring:        #0b2035;
    --zk-puls-flaeche:     rgba(0,82,141,0.15);
}

/* ==========================================================================
   2) BUEHNE + gescopte Leak-Resets
   style.css und vergleich.min.css fuehren unscoped Regeln fuer p, h3, aside und
   .icon; die Buehne setzt sie fuer ihren Teilbaum zurueck, ohne !important und
   ohne ausserhalb zu wirken.
   ========================================================================== */
.zk-buehne {
    position: relative;
    background: var(--zk-grund);
    border: 1px solid var(--zk-rahmen);
    border-radius: 0.5em;
    padding: 1.25em 1em;
    margin-bottom: 1em;
    min-height: 8em;
    color: var(--zk-typo);
}
.zinskorridore-dashboard .zk-buehne * { box-sizing: border-box; }
.zinskorridore-dashboard .zk-buehne p,
.zinskorridore-dashboard .zk-buehne h3 { margin: 0; padding: 0; }
.zinskorridore-dashboard .zk-buehne aside,
.zinskorridore-dashboard .zk-buehne aside p { margin: 0; padding: 0; background: none; border: 0; }
.zinskorridore-dashboard .zk-buehne .icon { position: static; margin: 0; font-size: inherit; }

/* Punkt-Modus-Ankuendigung (E11): fest, immer sichtbar, ueber der Leiter, ohne JS.
   Die Mint-Kante links ist mit E62 ENTFALLEN — die hinterlegte Flaeche traegt die
   Hervorhebung allein; der gruene Balken ist im Haus die Marke der positiven
   Kurzmeldung und sagte hier etwas, was ein Hinweis nicht meint. Der freigewordene
   optische Halt wandert nach innen: +0.3em Polster oben und unten (0.6em -> 0.9em).

   FLAECHE DUNKEL STATT MINT (Anwender-Entscheid 10.09.2026, nachdem die erste
   Fassung gemessen war): Ohne Kante muss die Flaeche allein absetzen — und
   rgba(169,246,219,0.10) tat das auf dem Seitengrund #0070C0 NICHT. Die Kante war
   hier das einzige sichtbare Merkmal.

   DER MASSSTAB IST DER RELATIVE, NICHT DER ABSOLUTE LUMINANZSPRUNG (praezisiert
   nach Review-Befund B1, der die erste Fassung dieses Absatzes zu Recht als
   widerspruechlich las): Ein absolutes Delta-L sagt fuer sich nichts, weil das Auge
   Helligkeitsunterschiede relativ zum Umfeld wertet. Gerechnet gegen den jeweils
   EIGENEN Grund:
     Uebersicht alt  rgb(0,112,192) -> rgb(17,125,195)   dL 0,0333 = 21,6 % — zu wenig
     Uebersicht neu  rgb(0,112,192) -> rgb(1,91,155)     dL 0,0554 = 36,0 % — traegt
     Panel (Mint)    rgb(8,89,147)  -> rgb(24,105,154)   dL 0,0333 = 35,8 % — traegt
   Dasselbe absolute dL, zwei verschiedene Antworten: der Panelgrund ist dunkler, und
   derselbe Sprung wiegt dort anderthalbmal so schwer. Deshalb behalten die
   Panel-Felder ihr Mint, und deshalb ist das kein Widerspruch zur Zeile darueber. Der naheliegende Griff — mehr Mint-Deckkraft —
   ist der falsche: er hellt den Grund auf und senkt den weissen Text unter die
   AA-Schwelle (0.14 -> 4,13:1, 0.18 -> 3,90:1; der Seitengrund selbst traegt
   5,15:1 und ist die Obergrenze). Die Gegenrichtung loest beides: rgba(4,26,45,0.25)
   im Buehnenton setzt gleich stark ab (Delta-L 0,057) und HEBT den Textkontrast auf
   7,15:1 — besser als der Zustand vor dieser Politur. Die Panel-Felder behalten ihr
   Mint: dort liegt die Flaeche auf dem dunklen Panelgrund und traegt gemessen.

   #vergleich IM SELEKTOR IST PFLICHT, NICHT KOSMETIK (gemessen 10.09.2026 per CDP
   an der Live-Seite): style.css fuehrt #vergleich p { padding: 0 5px 0 4px;
   line-height: 1.4em } mit (1,0,1). Gegen die frueheren (0,1,0) dieser Regel gewann
   der Bestand — das hier deklarierte Polster war seit Phase 2 TOT (gerendert 0 px
   oben und unten, 4 px links, 5 px rechts), und mit ihm die line-height 1.5. Erst
   (1,1,0) dreht das um. Kein !important: das Projekt loest solche Faelle durchgaengig
   ueber den Selektor (Lehre des ?v=12-Satzes, dort eine Stufe tiefer). */
#vergleich .zk-modushinweis {
    margin: 0 0 0.75em;
    padding: 0.9em 0.85em;
    background: rgba(4,26,45,0.25);
    color: var(--text-primary, #002b4d);
    font-size: 0.85rem;
    line-height: 1.5;
    border-radius: 0.25em;
}
#vergleich.kontrast-hell .zk-modushinweis {
    background: rgba(0,82,141,0.08);
    color: #003A66;
}

/* 2b) KURZERKLAERUNG UEBER DEM DIAGRAMM (Politur 16, 12.09.2026, E70)
   p.zk-intro steht als erstes Kind der Ergebniszone VOR .results-header — dort, wo
   Festgeld (p.zg-intro), Tagesgeld (p.skyline-intro) und Kreditkarte (p.fieber-intro)
   ihre Kurzerklaerung fuehren. Regel zeichengleich zu #vergleich .zg-intro der
   Festgeld-Ansicht, damit die Absaetze produktuebergreifend dieselbe Metrik tragen
   (Paritaet live gemessen 12.09.2026, Werte im CHANGELOG oben). Der Grund ist an
   dieser Stelle das Body-Blau durch das quasi-transparente Dashboard -> weisse
   Schrift; kontrast-hell macht den Grund weiss -> #003A66. #vergleich im Selektor,
   weil #vergleich p (1,0,1) sonst margin und line-height schluege (Lehre E62). Kein
   Polster deklariert: 0 5px 0 4px aus #vergleich p, wie bei der Festgeld-Intro. */
#vergleich .zk-intro {
    margin: 0.24rem 0 0.96rem;
    max-width: 44em;
    font-size: 0.96rem;
    line-height: 1.4;
    color: #ffffff;
}
#vergleich.kontrast-hell .zk-intro { color: #003A66; }
/* Dritter Satz (Anwender-Entscheid F3, 12.09.2026, ?v=24): zwei Fassungen im selben Absatz,
   Girokonto-Muster .panorama-intro-gross/-klein. Oberhalb 48em die lange Fassung (vier
   Saetze), darunter die Kurzfassung (zwei Saetze). Haltepunkt 48em wie das Bottom-Sheet
   und wie Girokonto - nicht 30em: die Kurzfassung ist die MOBILE Fassung, nicht eine
   Notloesung fuer die schmalste Stufe. Anlass (Live-VRT B1): bei 375 x 800 stand mit
   neun Zeilen (193,5 px) kein Band mehr im ersten Bildschirm. display statt visibility,
   damit die verborgene Fassung weder Platz nimmt noch vorgelesen wird. */
.zk-intro-klein { display: none; }
@media (max-width: 48em) {
    .zk-intro-gross { display: none; }
    .zk-intro-klein { display: inline; }
}

.zk-leer {
    margin: 0;
    color: var(--zk-typo-sek);
    font-size: 0.9rem;
    line-height: 1.6;
}

/* ==========================================================================
   3) RASTER — Achse, Zeilen und Median-Schicht teilen EIN Spaltenmodell,
   damit die Achse pixelgenau ueber den Baendern steht.

   Seit Phase 4 traegt .zk-zeile-flaeche dasselbe Modell: der Auslöser-Button liegt
   nach E39a ZWISCHEN .zk-zeile und ihren beiden Kindern (Label, Spur), also muss
   ER die beiden Spalten aufspannen, nicht mehr die Zeile allein. Bewusst derselbe
   Regelblock und keine zweite Werteliste — sonst laufen aeussere und innere
   Spaltenbreite beim naechsten Metrik-Wechsel auseinander, und genau das waere in
   der Buehne sofort als versetztes Band sichtbar. Der Core setzt an der Flaeche
   KEINE zk-raster-Klasse (Kontrakt §1), deshalb steht sie hier als eigener
   Selektor. Dasselbe Paar noch einmal im 48em-Haltepunkt, Abschnitt 13.
   ========================================================================== */
.zk-raster,
.zk-zeile-flaeche {
    display: grid;
    grid-template-columns: var(--zk-label-breite) minmax(0, 1fr);
    column-gap: var(--zk-spaltenabstand);
    align-items: center;
}

/* ==========================================================================
   4) ACHSE (sticky, Metrik in rem)
   Die negativen Margins ziehen den Achsenstreifen auf die volle Buehnenbreite,
   das gleich grosse Padding stellt den urspruenglichen Inhaltskasten wieder her —
   so verschwinden die Zeilen beim Scrollen vollstaendig unter der Achse, statt an
   den Buehnenraendern durchzuscheinen. Kein font-size auf .zk-achse, sonst
   veraendern sich die em-Werte gegenueber der Buehne.
   ========================================================================== */
.zk-achse {
    position: sticky;
    top: 0;
    z-index: 4;
    margin: -1.25em -1em 0.35rem;
    padding: 1.25em 1em 0;
    background: var(--zk-grund);
    border-radius: 0.5em 0.5em 0 0;
}
.zk-achse-spur {
    position: relative;
    height: 2.1rem;
    border-bottom: 1px solid var(--zk-achslinie);
}
.zk-tick { position: absolute; top: 0; bottom: 0; }
.zk-tick::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 1px;
    height: 0.4rem;
    background: var(--zk-achslinie);
}
.zk-tick-wert {
    position: absolute;
    bottom: 0.55rem;
    left: 0;
    transform: translateX(-50%);
    font-size: 0.7rem;
    line-height: 1;
    white-space: nowrap;
    color: var(--zk-tick-typo);
}
/* Erster und letzter Tick sitzen auf den Buehnenkanten: ihre Beschriftung kann dort
   nicht mittig ueber dem Teilstrich stehen, ohne die Buehne zu verlassen — und
   ausserhalb der Buehne gilt der Kontrast-Nachweis der Tick-Typo nicht mehr (dort
   liegt der Seitengrund #0070C0, nicht der Buehnengrund). Geklemmt wird deshalb
   weiterhin, aber an die AUSSENkante der Buehne statt an den Teilstrich: 0,75rem
   = 12 px sind das gemessene Buehnen-Padding (15,4 px auf dem Desktop, 12,8 px
   unter 48em) minus einem Rest Luft. Gegenueber der alten 0,1rem-Klemmung holt das
   12 px Abstand zum Nachbarlabel zurueck — genau die Strecke, an der das letzte
   Label bisher auf ALLEN Viewports mit dem vorletzten kollidierte (B1, VRT Phase 2:
   1200 -16,2 px · 640 -18,1 px · 375 -32,7 px).
   Die Ausduennung im Core rechnet mit denselben 12 px (zkTickBeschriftung). */
.zk-tick-erster .zk-tick-wert  { transform: translateX(-0.75rem); }
.zk-tick-letzter .zk-tick-wert { transform: translateX(-100%) translateX(0.75rem); }

/* Dichtestufen der Beschriftung (B1). WELCHE Teilstriche eine Beschriftung tragen,
   entscheidet der Core — nur er kennt ihre ANZAHL, und die schwankt mit der Domaene
   (18 bei 0-17%, 16 bei 2-17%, im Punkt-Modus auch nur 4). Hier faellt allein die
   Entscheidung, WELCHE Stufe bei welcher Viewport-Breite gilt (Abschnitt 13).
   Die drei Klassen stehen fuer "dieser Teilstrich traegt auf dieser Stufe eine
   Beschriftung"; jede Stufe waehlt ihren eigenen glatten Schritt und ist deshalb
   NICHT in der naechsten enthalten. Darum blendet jede Stufe aus UND wieder ein. */
.zk-tick:not(.zk-tick-weit) .zk-tick-wert { display: none; }

/* ==========================================================================
   5) LEITER + MEDIAN-LINIE
   ========================================================================== */
.zk-leiter {
    position: relative;
    padding-top: var(--zk-median-marke);
}
.zk-median-schicht {
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    pointer-events: none;
    align-items: stretch;
}
.zk-median-spur { position: relative; grid-column: 2; }
/* PHASE 5 (A5): left kommt aus --zk-median-x, das der Core inline setzt. Vorher
   stand dort direkt ein Inline-left — und ein Inline-Wert laesst sich aus einer
   Media-Query nur mit !important zuruecknehmen. Der Umweg ueber die Property macht
   den Haltepunkt in Abschnitt 13 ueberhaupt erst moeglich. Der Ersatzwert 50% ist
   nur die Notlage fuer den Fall, dass die Property fehlt; der Core setzt sie an
   beiden Knoten aus derselben Rechnung. */
.zk-median {
    position: absolute;
    left: var(--zk-median-x, 50%);
    top: var(--zk-median-marke);
    bottom: 0;
    width: 0;
    border-left: 0.125rem dashed var(--zk-median);
}
.zk-median-marke {
    position: absolute;
    left: var(--zk-median-x, 50%);
    top: 0;
    transform: translateX(-50%);
    font-size: 0.7rem;
    line-height: 1.2;
    white-space: nowrap;
    color: var(--zk-median);
}
.zk-median-marke-links  { transform: none; }
.zk-median-marke-rechts { transform: translateX(-100%); }

/* ==========================================================================
   6) ZEILE: Label-Spalte + Spur
   ========================================================================== */
/* scroll-margin-top haelt die angesprungene Zeile unter der STICKY Achse hervor.
   Ohne ihn landet die Zeile bei top: 0 und die Achse (gemessen 53 px hoch: 1,25em
   Polster + 2,1rem Spur) deckt ihre oberen 53 px zu — also Rangnummer, Anbieter,
   Produktname und die Spannenzeile. Wer im Pflichtblock auf den Anbieternamen
   klickt, um zur Leiter-Zeile zu kommen, saehe alles ausser dem Anbieternamen
   (B2, VRT Phase 2). 4rem = 64 px: die 53 px der Achse plus 11 px Luft. Unter 48em
   steht die Achse still, dort genuegt ein Rest Luft (Abschnitt 13). */
.zk-zeile { padding: 0.45rem 0; scroll-margin-top: 4rem; }
/* Trennlinie nur ZWISCHEN Zeilen. Bewusst nicht :first-of-type: die Median-Schicht
   ist ebenfalls ein div und waere dort das erste Element ihres Typs. */
.zk-zeile + .zk-zeile { border-top: 1px solid var(--zk-rahmen); }

.zk-zeile-label { min-width: 0; }
.zk-zeile-kopf {
    font-size: 0.85rem;
    line-height: 1.35;
    color: var(--zk-typo);
}
/* Positionsnummer als runder Badge — dieselbe Optik wie .produkt-rang der
   Listenansicht (Anwender-Entscheid 06.08.2026). Uebernommen sind Form, Gewicht und
   Grund, nicht die Desktop-Groesse: die Liste faehrt dort 48 px, das ist die Metrik
   einer Karten-Kopfzeile. Hier steht der Badge in einer 0.85rem-Textzeile ueber einem
   Korridor, und 48 px haetten das Zeilenraster der Leiter auseinandergezogen. 2rem ist
   der Wert, den die Liste selbst auf dem Telefon nimmt und den die kreative
   Girokonto-Ansicht fuer denselben Fall uebernommen hat — rem und nicht em, damit das
   Touch-Target nicht an der Schriftgroesse der Zeile haengt.
   inline-flex + vertical-align: middle statt inline-block: nur so zentriert die Zahl
   in beiden Achsen, ohne ueber line-height nachrechnen zu muessen. */
.zk-rang {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: middle;
    width: 2rem;
    height: 2rem;
    margin-right: 0.35em;
    border-radius: 50%;
    font-size: 0.875rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--zk-typo-sek);
    background: rgba(255,255,255,0.05);
}
/* Traegt die Zeile keinen eigenen Rang (geteilter Platz, __rangZeigen === false),
   bleibt der Knoten LEER im Dokument. Dann faellt nur der Grund weg — die FLAECHE
   bleibt stehen, damit die Anbieternamen der geteilten Plaetze mit dem Namen der
   ersten Zeile ihrer Gruppe fluchten. Genau das tut die Listenansicht mit ihrem
   leeren <div> im Grid; ohne diesen Platzhalter ruecken Folgezeilen einer Gruppe
   nach links aus und sehen aus wie eine andere Ebene.
   Kein display: none: der Knoten ist der Schreibort der Engine (schreibeRangKnoten)
   und muss nach einem Sortierklick wieder befuellbar sein. */
.zk-rang:empty { background: none; }
.zk-anbieter { font-weight: 700; }
.zk-produkt  { color: var(--zk-typo-sek); }
.zk-zeile-werte,
.zk-zeile-repr,
.zk-zeile-notizen {
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--zk-typo-sek);
}
.zk-zeile-werte { margin-top: 0.15rem; font-variant-numeric: tabular-nums; }
/* POLITUR 14 (E68, 12.09.2026): Banner "Festzins" in der Wertezeile der Zeilen mit
   festzins === true, an Stelle der Beschriftung "fester effektiver Jahreszins:".
   Zeichengleich zur Pille .rt-badge-pill.rt-badge-festzins der Tabelle bzw.
   a.produkt-badge.badge-festzins der Liste: Mint-Text, Mint-Kontur, neutral
   abdunkelnde Fuellung (die Liste hat die Fuellung am 25.07.2026 bewusst von Mint auf
   Schwarz-Transparenz gestellt, weil Mint-auf-Mint den Text nicht trug). Mint ist in
   dieser Ansicht die Farbe der Raute — bei Festzins faellt die Raute mit dem Punkt
   zusammen (E19), das Banner benennt genau diesen Fall. Rechnerisch 14,4:1 auf der
   abgedunkelten Buehne.
   Geometrie: inline-block auf der GRUNDLINIE des Zinssatzes, 0.68rem und line-height
   1.2 wie die Pille der Tabelle im Card-Modus — dieselbe Pillenhoehe wie dort
   (13,06 Zeile + 2 x 1,36 Polster + 2 x Rahmen; bei Root 16 px und 1-px-Rahmen
   17,77 px). Die Wertezeile misst ohne Banner 16,8 px (line-height 1.4em aus
   #vergleich p, das die 1.45 hier oben schlaegt — CT-0367) und waechst mit Banner um
   WENIGER ALS 1 PX — wie viel genau, haengt am Rahmenrendering der Messumgebung:
   0,97 px im Bau-Smoke (Rahmen 1 px), 0,31 px in der Review-Umgebung (Rahmen
   0,54 px bei devicePixelRatio 1,85). Bewusst hingenommen — Grundlinie ist die
   einzige Ausrichtung, bei der Bannertext und Zinssatz eine Linie teilen; middle
   wuerde die Zeile um ~1,5 px strecken, und ein Banner, das in 16,8 px passt,
   braeuchte line-height <= 1.04 oder vertical-align: top mit 1-px-Versatz zur
   Textmitte. FLIP misst Positionen je Sortierlauf und ist davon unberuehrt
   (Messwerte: Bau-Bericht und Review Politur 14). Deshalb prueft Gruppe (41) des
   Pruefskripts keine px-Sollhoehe, sondern die Invariante "Banner passt in die
   einzeilige Wertezeile".
   Kein Interaktions-Zustand: ein <span> in der <button>-Flaeche, keine eigene
   Bedienung (E39a). Kein Banner "bonitaetsabhaengig" — die Spanne zeigt es. */
.zk-badge-festzins {
    display: inline-block;
    margin-right: 0.15em;
    padding: 0.125em 0.5em;
    border: 1px solid rgba(169,246,219,0.5);
    border-radius: 0.25em;
    background: rgba(0,0,0,0.26);
    color: #A9F6DB;
    font-size: 0.68rem;
    font-weight: 600;
    line-height: 1.2;
    vertical-align: baseline;
    white-space: nowrap;
}
.zk-notiz-konflikt { color: var(--zk-konflikt); }
.zk-notiz-kante    { color: var(--zk-typo); }
/* Beispiel-Parameter (E9a) direkt hinter dem Rauten-Wert. Bewusst KEIN eigener
   Farbwert: die Parameter sind Beiwerk zur Zahl, kein eigener Zustand. */
.zk-zeile-bsp { white-space: normal; }
/* Sprungmarke auf den Pflichtblock-Eintrag (E12.4). SEIT PHASE 4 steht sie nicht
   mehr innerhalb von p.zk-zeile-repr, sondern als Geschwister der Ausloeser-Flaeche
   direkt im Zeilenraster (E39a). Ihre Platzierung im Raster und ihr eigenes
   Fokusbild stehen deshalb in Abschnitt 20b, nicht hier; Farbe und Unterstreichung
   bleiben unveraendert an dieser Stelle. Weiss + Unterstreichung statt
   einer Palettenfarbe: Mint, Blau und Violett sind in dieser Ansicht semantisch
   belegt (Raute, Cap, Konflikt), ein Link in einer davon behauptete eine Bedeutung.
   Drei Klassen im Selektor, damit die unscoped a-Regeln aus style.css nicht greifen. */
.zinskorridore-dashboard .zk-buehne .zk-sprung {
    color: var(--zk-typo);
    text-decoration: underline;
    white-space: nowrap;
}
.zinskorridore-dashboard .zk-buehne .zk-sprung:hover,
.zinskorridore-dashboard .zk-buehne .zk-sprung:focus { text-decoration: none; }

.zk-marker-staffel {
    display: inline-block;
    margin-right: 0.4rem;
    padding: 0.05rem 0.35rem;
    border: 1px solid var(--zk-achslinie);
    border-radius: 0.2rem;
    background: var(--zk-marker-grund);
    color: var(--zk-typo);
    font-size: 0.7rem;
    line-height: 1.5;
    white-space: nowrap;
}

/* ==========================================================================
   7) SPUR, BAND, CAPS, PUNKT
   Ueberlappung ist der Normalfall (E20): identische Spannen liegen deckungsgleich
   uebereinander. Getrennt wird ueber die Zeilentrennung, nicht ueber die Bandlage.
   ========================================================================== */
.zk-spur {
    position: relative;
    min-height: var(--zk-spurhoehe);
}
.zk-band {
    position: absolute;
    top: 50%;
    height: var(--zk-bandhoehe);
    /* Faellt ein Band schmaler aus als der Punkt, haelt min-width es sichtbar; die
       eigentliche Punkt-Darstellung entscheidet der Core ueber die Breite. */
    min-width: var(--zk-punktgroesse);
    margin-top: calc(var(--zk-bandhoehe) / -2);
    border-radius: calc(var(--zk-bandhoehe) / 2);
    background: linear-gradient(90deg, var(--zk-band-links), var(--zk-band-rechts));
}
/* Caps liegen INNEN an der Bandkante (P§6): aussen kollidieren sie bei Randnaehe
   mit der Label-Spalte bzw. mit dem Rauten-Wert. */
.zk-cap {
    position: absolute;
    top: -0.15rem;
    bottom: -0.15rem;
    width: 0.14rem;
    background: var(--zk-cap);
    border-radius: 0.07rem;
}
.zk-cap-lo { left: 0; }
.zk-cap-hi { right: 0; }
/* Endkappen-Behandlung der Randlage (E14): die belegte Kante wird hoeher und
   breiter. Seit dem 06.08.2026 eines von ZWEI Merkmalen (zusammen mit der
   verstaerkten Rautenkontur) — der vertikale Versatz der Raute ist entfallen. */
.zk-cap-kante { top: -0.4rem; bottom: -0.4rem; width: 0.22rem; }
/* Die DAUERHAFTE Marke der linken Kappe unter der Sortierung "Bestzins" (Knopf mit
   Kontur, Politur 13/E66) steht in Abschnitt 16b beim Sortier-Puls — sie haengt am
   selben Attribut data-sortbasis. */

.zk-punkt {
    position: absolute;
    top: 50%;
    width: var(--zk-punktgroesse);
    height: var(--zk-punktgroesse);
    margin-top: calc(var(--zk-punktgroesse) / -2);
    margin-left: calc(var(--zk-punktgroesse) / -2);
    border-radius: 50%;
    background: var(--zk-cap);
    border: 0.11rem solid var(--zk-band-rechts);
}

/* ==========================================================================
   8) RAUTE (§ 17-Marker) und ihre vier Lagen
   Zweifarbig (Fuellung + Kontur) — siehe Kontrast-Nachweis im Kopf.
   ========================================================================== */
.zk-raute {
    position: absolute;
    top: 50%;
    z-index: 3;
    width: var(--zk-rautengroesse);
    height: var(--zk-rautengroesse);
    margin-top: calc(var(--zk-rautengroesse) / -2);
    margin-left: calc(var(--zk-rautengroesse) / -2);
    background: var(--zk-raute-fuell);
    border: 0.1rem solid var(--zk-raute-kontur);
    transform: rotate(45deg);
}
/* Randlage (E14, neu gefasst 06.08.2026 auf Anwender-Entscheid): verstaerkte Kontur,
   KEIN Versatz nach oben mehr. Die Raute steht auch am Bestzins auf der vertikalen
   Mitte des Korridors — genau wie in den drei anderen Lagen. Bewusst KEINE eigene
   Farbe — die Palette in P§5 fuehrt keine Randlagen-Zeile, ein erfundener Ton
   waere ungeregelt.
   WARUM DAS TRAGFAEHIG BLEIBT: P§8 verlangt, dass Randlage und Konflikt sich nicht
   allein ueber Farbe unterscheiden. Das leisten weiterhin ZWEI Formmerkmale — die
   verstaerkte Kontur der Raute und die verstaerkte Endkappe (.zk-cap-kante) an der
   betroffenen Bandseite. Der Versatz war das dritte, nicht das einzige. */
.zk-raute-kante {
    border-width: 0.16rem;
}
/* Ueberschreitung (E13): eigener Ton, KEINE Klemmung auf die Bandkante. */
.zk-raute-konflikt {
    background: var(--zk-konflikt);
    border-color: var(--zk-konflikt-kontur);
}
/* Nur wenn die echte Position ausserhalb der ACHSE laege, wird auf die Achsenkante
   geklemmt — dann sichtbar als offene Doppelkontur markiert. */
.zk-raute-achsenrand {
    box-shadow: 0 0 0 0.16rem var(--zk-grund), 0 0 0 0.28rem var(--zk-konflikt);
}
/* Gestrichelte Spur von der Bandkante zur echten Rautenposition: macht die
   Ueberschreitung als Strecke lesbar und unterscheidet sie schon in der Form von
   der Randlage. */
.zk-konflikt-spur {
    position: absolute;
    top: 50%;
    height: 0.125rem;
    margin-top: -0.0625rem;
    z-index: 2;
    background: repeating-linear-gradient(90deg,
        var(--zk-konflikt) 0 0.2rem, rgba(0,0,0,0) 0.2rem 0.42rem);
}

/* ==========================================================================
   9) ANSICHTS-GLYPHE + NO-JS-FALLBACK (aus dem Core-Inline-<style> uebernommen)
   ========================================================================== */
/* Aktivierung 12.09.2026 (E69): Blaupause zg-/kb-view-icon der Schwesterprodukte,
   zeichengleich zum Inline-Reset in Listen-Core, Tabellen-Core und Seitenhilfe.
   Das <i> traegt seit E69 zusaetzlich die Klasse "icon" und erbt damit die
   Farbzustaende der Fontello-Nachbarn (Ruhe/Hover/aktiv/kontrast-hell aus style.css
   und vergleich.min.css) — eigene Farbregeln braucht es nicht mehr. Der Reset
   faengt die unscoped Geometrie der .icon-Regel (font-size 3em, position absolute,
   margin-left -1.6em) ab; Groessen-Kaskade wie die Nachbarn: Basis 1.85em,
   <= 88em 1.3em, <= 72em 1.2em. margin: 0 auto setzt die Glyphe mittig in die
   Zelle (gemessen: 0,01 px zur Mitte des Inhaltskastens, 1200 bis 1920 px). */
#hilfe .zk-view-icon { display: block; position: relative; margin: 0 auto; width: 1.3em; line-height: 1; font-size: 1.85em; }
#hilfe .zk-view-icon svg { width: 1.3em; height: 0.91em; vertical-align: -0.08em; display: inline-block; }
@media only screen and (max-width: 88em) {
    #hilfe .zk-view-icon { font-size: 1.3em; }
}
@media only screen and (min-width: 72.01em) and (max-width: 88em) {
    /* 88em-Band (Smoke-Befund B1, 12.09.2026): die Fontello-Nachbarn erben hier ihre
       Zeilenhoehe als feste Laenge (26,11 px = 1.7em der Zelle bei 15,36 px), der zk-Kasten
       mit line-height 1 misst 20,53 px und sitzt als Block oben im Zellen-Inhalt - seine
       Tinte stand 5,25 px hoeher als die der Nachbarn. 0.28em Polster oben gleicht die
       Kastenhoehe an (gemessen 26,11 px); Glyphenmitte danach 0,55 px ueber der
       Nachbar-Kastenmitte, wie oberhalb 88em (0,71 px). Nur in diesem Band: unterhalb
       72em zentriert die Flex-Zelle, oberhalb 88em sind beide Kaesten 28,42 px hoch. */
    #hilfe .zk-view-icon { padding-top: 0.28em; }
}
@media only screen and (max-width: 72em) {
    #hilfe .zk-view-icon { font-size: 1.2em; position: relative; margin: 0; }
}

/* Die Tabelle steht IMMER im DOM (Suchmaschinen, Screenreader) und ist sr-only.
   Seit Phase 2 ist sie kein No-JS-Ersatz mehr: die Leiter selbst rendert
   serverseitig und ist ohne JavaScript vollstaendig lesbar. Seit dem 06.08.2026 gibt
   es KEINEN sichtbaren Zustand mehr — der Umschalter aus Phase 3 und die Gegenregel
   .zk-fallback--sichtbar sind entfernt (Anwender-Entscheid). Diese Klammer ist damit
   der einzige Zustand der Tabelle.
   Die Klammer sitzt auf dem BLOCK-Wrapper, nicht auf der Tabelle: eine Tabelle mit
   width:1px dehnt sich auf ihre Mindestinhaltsbreite und riss den Seiten-Scroll-
   bereich auf (gemessen 1.510 px bei 1.185 px Viewport). Der Wrapper klemmt auf
   1 px; die Tabelle behaelt display:table und damit ihre Screenreader-Semantik. */
.zk-fallback {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   10) LEGENDE (P§1.7, Punkt 7 der Seitenreihenfolge)
   Sie steht auf dem BUEHNEN-GRUND, nicht auf dem Seitengrund. Das ist kein
   Dekor: eine Farbprobe muss auf demselben Untergrund stehen wie das, was sie
   erklaert — sonst gilt der Kontrast-Nachweis der Buehne fuer sie nicht.
   Jede Probe zieht ihre Farben aus den Custom Properties, nie aus kopierten
   Hexwerten; beim Palettenwechsel schalten sie deshalb mit.
   Die Proben liegen in einer Spalte fester Breite (--zk-probe-spalte), damit
   Grafik-Proben und der echte Staffel-Badge dieselbe Textkante ergeben.
   ========================================================================== */
.zk-legende {
    --zk-probe-spalte: 5.4rem;
    --zk-probe-breite: 3.2rem;
    background: var(--zk-grund);
    border: 1px solid var(--zk-rahmen);
    border-radius: 0.5em;
    padding: 0.9em 1em;
    margin-bottom: 1em;
    color: var(--zk-typo);
}
.zinskorridore-dashboard .zk-legende * { box-sizing: border-box; }
.zinskorridore-dashboard .zk-legende p { margin: 0; padding: 0; }
.zk-legende-titel {
    font-size: 0.8rem;
    font-weight: 700;
    line-height: 1.4;
    margin-bottom: 0.5rem;
}
.zk-legende-modus {
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--zk-typo-sek);
    margin-bottom: 0.6rem;
}
/* Auswahl-Erklaerung UNTER der Eintragsliste (Anwender-Auftrag 06.08.2026): sie sagt,
   wonach die Zeilen ueberhaupt ausgewaehlt sind. Zeichengleich zu .zk-legende-modus,
   nur der Abstand sitzt oben statt unten — der Satz folgt der Liste, statt ihr
   voranzugehen. Bewusst dieselbe Sekundaerfarbe: er erklaert den Rahmen der
   Darstellung und soll den Marken-Eintraegen darueber nicht die Aufmerksamkeit
   nehmen. */
.zk-legende-auswahl {
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--zk-typo-sek);
}
/* ⚠ DER ABSTAND BRAUCHT DIE VOLLE SPEZIFITAET, sonst ist er tot. Weiter oben steht
   .zinskorridore-dashboard .zk-legende p { margin: 0; padding: 0 } mit (0,2,1) — ein
   einfaches .zk-legende-auswahl (0,1,0) verliert dagegen, unabhaengig von der
   Reihenfolge. Live gemessen 06.08.2026: mit der kurzen Fassung margin-top 0px und
   Abstand zur Liste 0,00 px, mit dieser Fassung 11,2 px. Der Selektor ist nicht
   Zierde und darf nicht "vereinfacht" werden.
   Kein !important: die Spezifitaet reicht, und das Projekt loest solche Faelle
   durchgaengig ueber den Selektor (siehe die Panel-Regeln in Abschnitt 20). */
.zinskorridore-dashboard .zk-legende .zk-legende-auswahl { margin: 0.7rem 0 0; }
.zinskorridore-dashboard .zk-legende .zk-legende-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.5rem;
}
.zk-legende-eintrag {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
}
.zk-legende-text {
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--zk-typo-sek);
    min-width: 0;
}
.zk-legende-begriff { color: var(--zk-typo); font-weight: 700; }
/* Probenspalte. display:flex zentriert den einen echten Kindknoten (den
   Staffel-Badge); die Grafik-Proben zeichnen ueber Pseudoelemente und sind von
   der Flex-Achse unberuehrt. */
.zk-legende-probe {
    position: relative;
    flex: 0 0 var(--zk-probe-spalte);
    height: 1.35rem;
    display: flex;
    align-items: center;
}

/* ⚠ box-sizing fuer die MARKEN der Legende (Befund L1 des VRT, behoben 06.08.2026).
   Der globale border-box-Reset des Projekts erfasst PSEUDOELEMENTE NICHT — gemessen
   06.08.2026: ein frisch eingefuegtes <div> meldet border-box, sein ::after meldet
   content-box. Die Marken hier sind aber Pseudoelemente, die Raute in der Leiter ist
   ein echtes Element. Folge: dieselbe Zentrierung (top: 50% plus margin-top: -groesse/2)
   traf in der Leiter die Mitte und in der Legende nicht — dort ist die Box um zweimal
   die Rahmenbreite hoeher, die Marke sass also um genau EINE Rahmenbreite zu tief
   (gemessen: Raute und Konflikt +1,07 px, Punkt +1,62 px, Randlage +2,15 px; das
   rahmenlose Band als Kontrollprobe 0,00 px).

   DESHALB HIER border-box UND NICHT eine Korrektur der margin-top-Werte: Die Marken
   sollen zeigen, was die Leiter zeigt. Mit border-box rechnen sie ab jetzt nach
   DERSELBEN Regel wie das Original — gleiche Zentrierung und gleiche Aussengroesse
   (vorher war die Legenden-Raute um 2b groesser als die in der Leiter). Eine
   margin-Korrektur haette nur die Lage geflickt und die Groessendifferenz gelassen.

   NUR die Marken, nicht alle Proben: .zk-legende-median::before ist eine Linie aus
   width: 0 plus border-left. Fuer sie ist content-box konstitutiv, und sie hat keinen
   oberen Rahmen — sie zeigt den Fehler deshalb gar nicht (gemessen +0,01 px). */
.zk-legende-punkt::before,
.zk-legende-raute::after,
.zk-legende-konflikt::after,
.zk-legende-kante::after { box-sizing: border-box; }

/* Zinsspanne: Band mit den beiden innenliegenden Endkappen. Die Kappen entstehen
   als zwei harte Stopps EINES Gradienten — so braucht das zweite Pseudoelement
   nicht fuer jede Kappe einzeln herhalten. */
.zk-legende-band::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: var(--zk-probe-breite);
    height: var(--zk-bandhoehe);
    margin-top: calc(var(--zk-bandhoehe) / -2);
    border-radius: calc(var(--zk-bandhoehe) / 2);
    background: linear-gradient(90deg, var(--zk-band-links), var(--zk-band-rechts));
}
.zk-legende-band::after {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: var(--zk-probe-breite);
    height: calc(var(--zk-bandhoehe) + 0.3rem);
    margin-top: calc((var(--zk-bandhoehe) + 0.3rem) / -2);
    background: linear-gradient(90deg,
        var(--zk-cap) 0 0.14rem,
        rgba(0,0,0,0) 0.14rem calc(100% - 0.14rem),
        var(--zk-cap) calc(100% - 0.14rem) 100%);
}

/* Einzelner Zinssatz: derselbe Punkt wie in der Leiter. */
.zk-legende-punkt::before {
    content: '';
    position: absolute;
    top: 50%;
    left: calc(var(--zk-probe-breite) / 2);
    width: var(--zk-punktgroesse);
    height: var(--zk-punktgroesse);
    margin-top: calc(var(--zk-punktgroesse) / -2);
    margin-left: calc(var(--zk-punktgroesse) / -2);
    border-radius: 50%;
    background: var(--zk-cap);
    border: 0.11rem solid var(--zk-band-rechts);
}

/* § 17-Wert: Raute AUF einem Bandstueck — so, wie sie in der Leiter steht.
   Eine Raute auf blankem Grund zeigte einen anderen Kontrastfall als den
   nachgewiesenen. */
.zk-legende-raute::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: var(--zk-probe-breite);
    height: var(--zk-bandhoehe);
    margin-top: calc(var(--zk-bandhoehe) / -2);
    border-radius: calc(var(--zk-bandhoehe) / 2);
    background: linear-gradient(90deg, var(--zk-band-links), var(--zk-band-rechts));
}
.zk-legende-raute::after {
    content: '';
    position: absolute;
    top: 50%;
    left: calc(var(--zk-probe-breite) / 2);
    width: var(--zk-rautengroesse);
    height: var(--zk-rautengroesse);
    margin-top: calc(var(--zk-rautengroesse) / -2);
    margin-left: calc(var(--zk-rautengroesse) / -2);
    background: var(--zk-raute-fuell);
    border: 0.1rem solid var(--zk-raute-kontur);
    transform: rotate(45deg);
}

/* Markt-Mittel: gestrichelte Senkrechte, Strichstaerke wie .zk-median. */
.zk-legende-median::before {
    content: '';
    position: absolute;
    top: 0.1rem;
    bottom: 0.1rem;
    left: calc(var(--zk-probe-breite) / 2);
    width: 0;
    border-left: 0.125rem dashed var(--zk-median);
}

/* Ueberschreitung (E13): gestrichelte Strecke plus Raute im Konflikt-Ton am
   Ende — dieselbe Kombination aus Form UND Farbe wie in der Leiter (P§8). */
.zk-legende-konflikt::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 0.2rem;
    width: calc(var(--zk-probe-breite) - 0.9rem);
    height: 0.125rem;
    margin-top: -0.0625rem;
    background: repeating-linear-gradient(90deg,
        var(--zk-konflikt) 0 0.2rem, rgba(0,0,0,0) 0.2rem 0.42rem);
}
.zk-legende-konflikt::after {
    content: '';
    position: absolute;
    top: 50%;
    left: calc(var(--zk-probe-breite) - 0.5rem);
    width: var(--zk-rautengroesse);
    height: var(--zk-rautengroesse);
    margin-top: calc(var(--zk-rautengroesse) / -2);
    margin-left: calc(var(--zk-rautengroesse) / -2);
    background: var(--zk-konflikt);
    border: 0.1rem solid var(--zk-konflikt-kontur);
    transform: rotate(45deg);
}

/* Randlage (E14): Bandstueck mit VERSTAERKTER rechter Endkappe, darauf die Raute mit
   verstaerkter Kontur. Ohne eigene Farbe — die Verstaerkung traegt allein die Form,
   genau wie in der Leiter. Die Raute sitzt seit dem 06.08.2026 auf der vertikalen
   Mitte, nicht mehr darueber; die Probe muss das zeigen, sonst verspricht die
   Legende eine Optik, die die Leiter nicht mehr liefert. */
.zk-legende-kante::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: var(--zk-probe-breite);
    height: calc(var(--zk-bandhoehe) + 0.5rem);
    margin-top: calc((var(--zk-bandhoehe) + 0.5rem) / -2);
    background: linear-gradient(90deg,
        rgba(0,0,0,0) 0 calc(100% - 0.22rem),
        var(--zk-cap) calc(100% - 0.22rem) 100%);
}
.zk-legende-kante::after {
    content: '';
    position: absolute;
    top: 50%;
    left: var(--zk-probe-breite);
    width: var(--zk-rautengroesse);
    height: var(--zk-rautengroesse);
    margin-top: calc(var(--zk-rautengroesse) / -2);
    margin-left: calc(var(--zk-rautengroesse) / -2 - 0.11rem);
    background: var(--zk-raute-fuell);
    border: 0.16rem solid var(--zk-raute-kontur);
    transform: rotate(45deg);
}
/* Das Bandstueck der Randlagen-Probe liegt hinter der verstaerkten Kappe: ohne
   diesen zweiten Traeger fehlte der Bezug, wovon die Kappe die Kante ist. */
.zk-legende-kante {
    background-image: linear-gradient(90deg, var(--zk-band-links), var(--zk-band-rechts));
    background-size: var(--zk-probe-breite) var(--zk-bandhoehe);
    background-position: left center;
    background-repeat: no-repeat;
    border-radius: calc(var(--zk-bandhoehe) / 2);
}

/* ==========================================================================
   11) § 17-FUSSNOTE (P§1.8) und 12) PFLICHTBLOCK (E12)
   Beide stehen auf dem SEITEN-Grund, nicht auf der Buehne: es ist Fliesstext,
   kein Diagramm-Bestandteil, und er muss auch dann lesbar sein, wenn die Buehne
   gar nichts zeigt (Leerzustand). Farbfuehrung deshalb ueber die Dashboard-
   Variablen wie beim Punkt-Modus-Hinweis, nicht ueber die zk-Palette.
   ========================================================================== */
/* Kante entfallen mit E62 (siehe .zk-modushinweis), Polster +0.3em oben und unten
   (0.7em -> 1em). Der WORTLAUT dieses Blocks bleibt unangetastet — E45 betrifft den
   Text der Pflichtangabe, nicht ihre Flaechenoptik. */
.zk-fussnote {
    margin: 0 0 1em;
    padding: 1em 0.9em;
    background: rgba(4,26,45,0.25);   /* dunkel statt Mint, siehe .zk-modushinweis */
    border-radius: 0.25em;
}
.zinskorridore-dashboard .zk-fussnote p { margin: 0; padding: 0; }
/* ALLE Textstufen dieser beiden Bloecke laufen auf --text-primary. Grund ist
   gemessen, nicht Geschmack: der Live-Seitengrund ist #0070C0 (25.07.2026 im
   Browser abgelesen, nicht das erwartete Dunkelblau). Darauf erreicht weisser
   Text 5,15:1 — und das ist die OBERGRENZE. --text-secondary kaeme auf 3,32:1,
   --text-muted auf 2,40:1, beide unter der AA-Schwelle 4,5:1 fuer Fliesstext.
   Fuer eine Pflichtangabe nach § 17 PAngV ist das die falsche Sparsamkeit.
   Die Hierarchie tragen deshalb Schriftgroesse und -schnitt, nicht die Farbe. */
.zk-fussnote-regel,
.zk-fussnote-vorbehalt {
    font-size: 0.8rem;
    line-height: 1.55;
    color: var(--text-primary, #fff);
    max-width: 60em;
}
.zk-fussnote-vorbehalt { margin-top: 0.45em; }
/* Nur die Flaeche braucht eine Hell-Regel (bis E62 war es Flaeche plus Kante).
   Die Textfarben kommen aus den
   Dashboard-Variablen, und vergleich.min.css tauscht die unter kontrast-hell
   bereits selbst (--text-primary #fff -> #111, --text-secondary -> rgba(0,0,0,.88),
   --text-muted -> #404040). Eigene Hexwerte hier waeren eine zweite Quelle, die
   beim naechsten Bestands-Update auseinanderliefe. */
#vergleich.kontrast-hell .zk-fussnote {
    background: rgba(0,82,141,0.06);
}

/* Pflichtblock. Kompakte Typografie ist hier das ausdrueckliche Gegenmittel zur
   Seitenlaenge (Anwender-Entscheid C3) — gekuerzt wird der Beispieltext NICHT.
   Deshalb: kein Kachel-Padding je Eintrag, nur Haarlinien als Trenner. */
.zk-pflichtblock {
    margin: 0 0 1em;
    color: var(--text-primary, #fff);
}
.zinskorridore-dashboard .zk-pflichtblock * { box-sizing: border-box; }
.zinskorridore-dashboard .zk-pflichtblock p { margin: 0; padding: 0; }
.zinskorridore-dashboard .zk-pflichtblock .zk-pflichtblock-titel {
    margin: 0 0 0.3em;
    padding: 0;
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.35;
    color: var(--text-primary, #fff);
}
.zk-pflichtblock-hinweis {
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--text-primary, #fff);
    max-width: 60em;
    margin-bottom: 0.6em;
}
.zinskorridore-dashboard .zk-pflichtblock .zk-pflicht-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--border-light, rgba(255,255,255,0.06));
}
.zk-pflicht-eintrag {
    padding: 0.55em 0;
    border-bottom: 1px solid var(--border-light, rgba(255,255,255,0.06));
    /* Sprungziel aus der Leiter-Zeile. Der Pflichtblock liegt unterhalb der Buehne;
       wenn er oben im Bild steht, ist ihr Container aus dem Bild und die Achse klebt
       nicht mehr — ein Achsen-Versatz waere hier falsch. Der kleine Wert ist nur
       Luft ueber dem angesprungenen Eintrag (B2, VRT Phase 2). */
    scroll-margin-top: 0.5rem;
}
.zk-pflicht-kopf {
    font-size: 0.8rem;
    line-height: 1.4;
    margin-bottom: 0.15em;
}
/* Zweiter Ort derselben Positionsnummer (Anwender-Entscheid 06.08.2026: beide
   Bereiche im Listen-Stil). Gleiche Geometrie wie .zk-rang in der Leiter, aber die
   Farbfuehrung laeuft ueber die DASHBOARD-Variablen und nicht ueber die zk-Palette:
   der Pflichtblock steht auf dem Seitengrund, nicht auf der Buehne — dieselbe
   Trennung, die schon fuer .zk-fussnote und den restlichen Blocktext gilt.
   DIE SCHRIFTFARBE BLEIBT --text-primary und wird NICHT auf --text-secondary
   gesenkt, obwohl die Listenansicht ihren Badge so faehrt: der Live-Seitengrund
   dieses Blocks ist #0070C0, dort kommt --text-secondary auf 3,32:1 und damit unter
   die AA-Schwelle 4,5:1 (der Kasten zur Fussnote weiter oben hat das gemessen). Eine
   0.875rem-Ziffer ist auch in 700 kein "large text", die Schwelle gilt voll. Auf der
   Buehne ist das anders — dort traegt .zk-rang den geprueften --zk-typo-sek. */
.zk-pflicht-rang {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: middle;
    width: 2rem;
    height: 2rem;
    margin-right: 0.35em;
    border-radius: 50%;
    font-size: 0.875rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary, #fff);
    background: rgba(255,255,255,0.05);
}
.zk-pflicht-rang:empty { background: none; }
/* Der Anbietername IST der Ruecksprung auf die Leiter-Zeile — dafuer entsteht
   kein zusaetzliches Element, der Name steht ohnehin da. Drei Klassen im
   Selektor gegen die unscoped a-Regeln aus style.css. */
.zinskorridore-dashboard .zk-pflichtblock .zk-pflicht-zurueck {
    color: var(--text-primary, #fff);
    font-weight: 700;
    text-decoration: underline;
}
.zinskorridore-dashboard .zk-pflichtblock .zk-pflicht-zurueck:hover,
.zinskorridore-dashboard .zk-pflichtblock .zk-pflicht-zurueck:focus { text-decoration: none; }
/* Fliesstext des Beispiels. Klassen .beispiel-effzins und .beispiel-pa kommen aus
   den Pipeline-Transformatoren und sind hier zeichengleich zu Liste und Tabelle
   gestylt: das <strong> bleibt semantisch im Markup (§ 17 Abs. 2 S. 2 PAngV),
   wird aber optisch neutralisiert (Anwender-Entscheid Politur 09.07.2026). Eine
   dritte, abweichende Optik derselben Pflichtangabe waere Cross-View-Drift. */
.zk-beispiel-text {
    font-size: 0.8rem;
    line-height: 1.55;
    color: var(--text-primary, #fff);
    max-width: 60em;
}
.zk-beispiel-text .beispiel-effzins { font-weight: inherit; color: var(--text-primary, #fff); }
/* Groesse zeichengleich zu Liste und Tabelle, FARBE bewusst nicht: dort traegt
   "p. a." --text-muted, das sind auf dem gemessenen Seitengrund 2,40:1. In einem
   Pflichtblock ist auch der Periodenzusatz Pflichttext. Benannte Abweichung. */
.zk-beispiel-text .beispiel-pa {
    font-size: 0.68rem;
    color: var(--text-primary, #fff);
    font-weight: 500;
}
/* Kursiv als Unterscheidung, nicht Aufhellung — siehe Kontrast-Begruendung oben. */
.zk-beispiel-text em { font-style: italic; }
/* Der Darlehensgeber ist Pflichtangabe nach § 17 Abs. 2 Nr. 1 PAngV und bekommt
   deshalb die volle Textfarbe — kleiner ja, schwaecher nein. */
.zk-darlehensgeber {
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--text-primary, #fff);
    margin-top: 0.1em;
}
.zk-darlehensgeber-label { font-weight: 600; }
/* Hell-Modus: nur die zwei Stellen, die NICHT ueber die Dashboard-Variablen
   laufen. Werte zeichengleich aus Liste (Z. 1281) und Tabelle (Z. 1588). */
#vergleich.kontrast-hell .zk-beispiel-text .beispiel-effzins { color: #00528D; }
#vergleich.kontrast-hell .zinskorridore-dashboard .zk-pflichtblock .zk-pflicht-zurueck { color: #00528D; }

/* ==========================================================================
   13) SCHMALE VIEWPORTS
   Vollwertige Mobile-Ausarbeitung (Mini-Skala je Karte, P§8) ist Phase 5. Hier
   nur so viel, dass die Leiter unter 48em nicht bricht und kein horizontaler
   Seiten-Overflow entsteht: Label ueber die Spur, sticky Achse entfaellt.
   Die Bedienelemente aus Phase 3 tragen ihre schmalen Viewports NICHT hier,
   sondern in ihren eigenen Abschnitten 14 und 15. Grund: ihre Antwort ist
   ueberwiegend gar kein Haltepunkt, sondern Umbruch (flex-wrap) bzw. ein
   scrollender Wrapper — was hier steht, sind Haltepunkte der Leiter-Geometrie,
   und beides zu mischen machte weder das eine noch das andere lesbarer.
   ========================================================================== */
@media (max-width: 60em) {
    .zk-buehne { --zk-label-breite: 12rem; }
}
/* --- MINI-SKALA JE KARTE (Phase 5, A2; P§8) ------------------------------
   Grundzustand: NICHT DA. Auf dem Desktop traegt die sticky Achse den Massstab
   fuer alle Zeilen gemeinsam; eine zweite Skala je Zeile waere dort reine
   Wiederholung. Sichtbar wird sie erst im Kartenmodus, wo die Achse entfaellt.

   Sie liegt als DRITTE Zelle im Raster der Ausloeser-Flaeche und damit in
   derselben Spalte wie .zk-spur — nur deshalb steht ein Teilstrich bei 40% exakt
   unter dem Bandwert bei 40%. Wer die Spaltenaufteilung des Kartenmodus aendert,
   aendert diese Zuordnung mit.

   Klassen bewusst NICHT von .zk-tick geerbt: dort sitzt der Teilstrich unten und
   die Beschriftung darueber (die Achse steht UEBER der Leiter), hier genau
   umgekehrt (die Skala steht UNTER dem Band). Ein gemeinsamer Regelblock haette
   an jeder zweiten Eigenschaft eine Ausnahme gebraucht. */
.zk-mini-skala { display: none; }
.zk-mini-tick { position: absolute; top: 0; }
.zk-mini-tick::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 1px;
    height: 0.3rem;
    background: var(--zk-achslinie);
}
.zk-mini-wert {
    position: absolute;
    top: 0.45rem;
    left: 0;
    transform: translateX(-50%);
    font-size: 0.65rem;
    line-height: 1;
    white-space: nowrap;
    color: var(--zk-tick-typo);
}
/* Erster und letzter Wert an die Kartenkante geklemmt statt mittig ueber ihrem
   Teilstrich — mittig ragten sie ueber den Kartenrand hinaus. Anders als bei der
   grossen Achse braucht es hier KEINEN zusaetzlichen Versatz nach innen: das
   Kartenpolster liefert den Abstand zur Kante bereits. */
.zk-mini-tick-erster .zk-mini-wert  { transform: translateX(0); }
.zk-mini-tick-letzter .zk-mini-wert { transform: translateX(-100%); }

@media (max-width: 48em) {
    /* .zk-zeile-flaeche geht mit — Begruendung im Kopf von Abschnitt 3. Faellt sie
       hier aus, behaelt die Auslöser-Flaeche ihre 17rem-Labelspalte, waehrend die
       Zeile darum herum schon einspaltig ist: die Spur rutschte aus der Buehne. */
    .zk-raster,
    .zk-zeile-flaeche {
        grid-template-columns: minmax(0, 1fr);
        column-gap: 0;
    }
    /* Ein Wert fuer BEIDE Seiten des Kartenpolsters — die Karte setzt ihn als
       padding, die Median-Schicht als gleich grosses padding auf ihr eigenes
       Raster. Zwei getrennte Zahlen liefen beim naechsten Metrik-Wechsel
       auseinander, und die gestrichelte Linie stuende dann neben den Baendern,
       die sie erklaert. */
    .zk-buehne {
        --zk-karte-polster: 0.75rem;
        /* Die Marke unter dem Kartenmodus bricht auf zwei Zeilen um (siehe unten);
           der reservierte Streifen ueber der Leiter muss dafuer reichen, sonst
           liegt sie auf der ersten Karte. */
        --zk-median-marke: 2.6rem;
    }
    /* DIE ACHSE ENTFAELLT (P§8 woertlich: "Die sticky Desktop-Achse entfaellt").
       Nicht nur ihr sticky: jede Karte traegt ab hier ihre eigene Skala, und zwei
       Massstaebe fuer dieselbe Groesse auf einem Bildschirm sind eine Zumutung.
       Der Wertebereich bleibt fuer Screenreader im aria-label der Buehne stehen,
       und jede Zeile fuehrt ihre drei Zinswerte ohnehin als Text. */
    .zk-achse { display: none; }
    /* Die Median-Schicht bekommt dasselbe Polster wie die Karten, damit ihre
       Spur exakt so breit ist wie die Spur INNERHALB einer Karte. Ohne das
       stuende die Linie um das Kartenpolster versetzt neben den Baendern. */
    .zk-median-schicht {
        grid-template-columns: minmax(0, 1fr);
        padding-left: var(--zk-karte-polster);
        padding-right: var(--zk-karte-polster);
    }
    .zk-median-spur { grid-column: 1; }
    /* A5 / VRT-Befund N2: die Marke ist mit "Markt-Mittel (Median laut
       Kreditbeispielen): 7,49% p. a." breiter als die Spur selbst — bei 320 px
       stand ihr linkes Ende 22,1 px ausserhalb des Bildes. Die drei Lagen
       (mittig / -links / -rechts) helfen dagegen nicht: ein Kasten, der breiter
       ist als sein Bezugsraum, ragt in JEDER Lage heraus. Sie steht deshalb im
       Kartenmodus linksbuendig ueber der vollen Spurbreite und darf umbrechen.
       Die Ortsangabe geht dabei nicht verloren — die gestrichelte LINIE bleibt
       an ihrer echten Position (sie behaelt ihr --zk-median-x).
       Die beiden Lage-Klassen sind ausdruecklich mitgenannt: sie haben dieselbe
       Spezifitaet, und ohne Nennung entschiede allein die Reihenfolge im
       Stylesheet darueber, ob die Korrektur greift. */
    .zk-median-marke,
    .zk-median-marke-links,
    .zk-median-marke-rechts {
        left: 0;
        max-width: 100%;
        transform: none;
        white-space: normal;
    }
    /* --- A1: DIE ZEILE WIRD ZUR KARTE ------------------------------------
       Label oben, Band darunter ueber die volle Breite — das leistet schon das
       einspaltige Raster oben. Was die KARTE ausmacht, ist der eigene Grund mit
       Rahmen und Radius: einspaltig gestapelt und nur durch eine Haarlinie
       getrennt, laufen Anbietername, Werte, Band und Skala der einen Zeile
       optisch in die naechste. Farben ausschliesslich aus den Custom Properties
       der Buehne (E30), damit die Karte beide Paletten mitnimmt.
       Waagerechtes Polster ist hier KEIN Dekor: ohne es klebten Anbietername und
       die Enden der Mini-Skala am Kartenrand. Es ist der Grund, warum die
       Median-Schicht darueber dasselbe Polster tragen muss. */
    .zk-zeile {
        padding: 0.6rem var(--zk-karte-polster);
        margin-bottom: 0.5rem;
        border: 1px solid var(--zk-rahmen);
        border-radius: 0.4rem;
        background: var(--zk-marker-grund);
        scroll-margin-top: 0.5rem;
    }
    /* Die Trennregel .zk-zeile + .zk-zeile aus Abschnitt 6 braucht hier KEINE
       Ruecknahme und bekommt bewusst keine: sie setzt border-top auf denselben
       Wert, den der Kartenrahmen ohnehin traegt. Sie ueberschreibt die obere
       Kante der Karte mit einer identischen Kante — sichtbar aendert sich nichts,
       und eine Ruecknahme auf 0 loeschte die Oberkante jeder Karte ausser der
       ersten. Geprueft an allen drei Messbreiten (1200/375/320). */
    .zk-spur { min-height: 2rem; }
    /* A2: hier wird die Skala sichtbar. Die Hoehe traegt Teilstrich (0,3rem) und
       Beschriftung (ab 0,45rem, 0,65rem hoch) ohne Ueberlauf. */
    .zk-mini-skala {
        display: block;
        position: relative;
        height: 1.35rem;
        margin-top: 0.3rem;
        border-top: 1px solid var(--zk-achslinie);
    }
    /* Zweite Dichtestufe der Skalenbeschriftung: Spur 427-673 px. Dieselbe Stufe
       und dieselbe Schwelle, die vorher die grosse Achse getragen hat — der Core
       rechnet sie in zkTickBeschriftung() und gibt die Vereinigung beider Stufen
       aus. Jede Stufe blendet AUS und wieder EIN, weil die Stufen ihren eigenen
       glatten Schritt waehlen und deshalb nicht ineinander enthalten sind. */
    .zk-mini-tick:not(.zk-mini-tick-mittel) .zk-mini-wert { display: none; }
    .zk-mini-tick.zk-mini-tick-mittel .zk-mini-wert { display: block; }
    /* Legende: schmalere Probenspalte, damit der Text nicht auf zwei Zeichen je
       Zeile zusammenfaellt. Der Staffel-Badge (breiteste Probe) passt bei
       4,4rem noch ohne Umbruch — er traegt white-space: nowrap. */
    .zk-legende { --zk-probe-spalte: 4.4rem; --zk-probe-breite: 2.6rem; }
    .zk-legende-eintrag { gap: 0.5rem; }
}
/* Dritte Dichtestufe der Skalenbeschriftung. Eigener Haltepunkt, weil die Spur
   innerhalb des 48em-Bandes von 673 px (bei 768 px Viewport, einspaltig und ohne
   Label-Spalte) auf 270 px (bei 320 px) faellt — eine einzige Stufe fuer dieses
   Band muesste sich am schmalsten Fall ausrichten und liesse bei 700 px die halbe
   Skala unbeschriftet. Unter 30em: Spur 270-427 px. */
@media (max-width: 30em) {
    .zk-mini-tick:not(.zk-mini-tick-eng) .zk-mini-wert { display: none; }
    .zk-mini-tick.zk-mini-tick-eng .zk-mini-wert { display: block; }
}

/* ==========================================================================
   14) SORTIERLEISTE (Phase 3, P§1 Punkt 5)

   Sie steht UEBER der Buehne und damit ausserhalb von deren Custom Properties —
   ein var(--zk-...) waere hier leer. Die Optik ist deshalb bewusst die der
   Bestands-Bedienelemente, damit die dritte Ansicht wie eine Schwester von Liste
   und Tabelle wirkt:
     Segmentgruppe = .toggle-group aus vergleich.min.css?v=18
                     (background rgba(0,82,141,0.4), radius 8px, padding 2px)
     Segment       = .toggle-btn  (13px, weight 500, radius 6px, 150ms ease;
                     aktiv: heller Grund, Text --primary-darker, weight 600)
     Richtungsknopf= .filter-reset-btn aus dem Inline-Block des Cores
                     (Haarlinienrahmen, radius 0.3em)
   Uebernommen sind die Werte, nicht die Klassen: die Bestandsklassen tragen unter
   .no-js ein cursor:default + opacity:.6 (vergleich.min.css), weil sie dort ohne
   JavaScript wirkungslos sind. Diese Leiste ist ein echtes POST-Formular und
   funktioniert ohne JavaScript — sie darf nicht als deaktiviert erscheinen.
   px-Werte der Quelle sind in em/rem uebersetzt (2px -> 0.125rem, 6px -> 0.375rem,
   8px -> 0.5rem, 13px -> 0.8125rem); nur der Haarlinienrahmen bleibt 1px, das ist
   die im Kopf dokumentierte Ausnahme.

   SCHMALE VIEWPORTS ohne Haltepunkt: die Leiste und die Segmentgruppe brechen um
   (flex-wrap); zusammen mit flex: 1 1 auto ordnen sich die Segmente von selbst.
   Der einzige Haltepunkt unten (30em) gibt Label und Gruppe je eine eigene Zeile,
   damit die Gruppe nicht neben dem Label eingequetscht wird.

   PHASE 5 (A7): DIE SEGMENTE BRECHEN JETZT UM — white-space: normal statt nowrap.
   Hier stand bis zur Phase 5 die Zusicherung, kein Segment werde breiter als
   320 px, gestuetzt auf "das breiteste Label ('Zwei-Drittel-Zins') misst 105 px".
   Der Anwender-Entscheid vom 31.07.2026 ersetzt genau dieses Label durch
   "effektiver Jahreszins des repraesentativen Kreditbeispiels" — 55 statt 17
   Zeichen, bei 0,8125rem rund 350 px. Mit dem alten nowrap haette die Leiste bei
   320 px Viewport einen horizontalen Seiten-Overflow erzeugt: die Zusicherung war
   nicht falsch aufgeschrieben, sie hat schlicht ihre Grundlage verloren.
   Der Preis des Umbruchs ist, dass ein Begriff mitten im Wort brechen kann. Das
   ist bei einem 55 Zeichen langen Begriff ohnehin unvermeidlich und deutlich
   harmloser als eine Steuerung, die aus dem Bild laeuft.
   ========================================================================== */
.zk-sortierleiste {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin: 0 0 0.75em;
}
.zk-sort-label {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-primary, #fff);
    white-space: nowrap;
}
.zk-sort-segmente {
    display: flex;
    flex-wrap: wrap;
    gap: 0.125rem;
    padding: 0.125rem;
    background: rgba(0,82,141,0.4);
    border-radius: 0.5rem;
}
.zk-sort-segment {
    flex: 1 1 auto;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.3;
    padding: 0.5em 1em;
    border: 0;
    border-radius: 0.375rem;
    background: transparent;
    color: rgba(255,255,255,0.88);
    /* PHASE 5 (A7): siehe Abschnitt-Kopf. min-width: 0 gehoert zwingend dazu —
       ohne ihn haelt ein Flex-Element seine min-content-Breite und der Umbruch
       verhinderte den Overflow nur auf dem Papier. */
    white-space: normal;
    min-width: 0;
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}
.zk-sort-segment:hover { background: rgba(255,255,255,0.10); color: #fff; }
.zk-sort-segment.active {
    background: var(--text-primary, #fff);
    color: #004578;
    font-weight: 600;
}
.zk-sort-richtung {
    flex: 0 0 auto;
    font: inherit;
    font-size: 0.8125rem;
    line-height: 1.3;
    padding: 0.45em 0.8em;
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 0.3em;
    background: rgba(255,255,255,0.08);
    color: var(--text-primary, #fff);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 150ms ease;
}
.zk-sort-richtung:hover { background: rgba(255,255,255,0.15); }
/* Der Richtungspfeil ist ein Pseudoelement aus data-richtung und KEIN DOM-Knoten:
   die Engine darf die Beschriftung per textContent ersetzen, ohne ein Kindelement
   zu zerstoeren, und der Pfeil folgt dem Attribut automatisch. Fuer Screenreader
   ist er unsichtbar, weil das aria-label des Knopfes seinen Inhalt ersetzt. */
.zk-sort-richtung::before { content: "\2191\00a0"; }
.zk-sort-richtung[data-richtung="desc"]::before { content: "\2193\00a0"; }

/* Fokus-Sichtbarkeit aller neuen Bedienelemente. Zeichengleich zur Bestandsregel
   im Core-Inline-Block (.sub-auswahl .toggle-btn:focus-visible), nur 2px in rem
   uebersetzt, damit der Ring bei Zoom mitwaechst. */
.zk-sort-segment:focus-visible,
.zk-sort-richtung:focus-visible {
    outline: 0.125rem solid var(--accent, #A9F6DB);
    outline-offset: 0.125em;
}

/* Einziger Haltepunkt der Leiste. Er tut zwei Dinge, die der freie Umbruch nicht
   von allein richtig macht: Label und Segmentgruppe bekommen je eine eigene Zeile,
   und die Segmente eine 50%-Basis. Ohne die Basis ordnete der freie Umbruch bei
   360 px gemessen 3+1 an (drei schmale oben, "Anbieter" ueber die volle Breite
   darunter) — kein Fehler, aber ein unruhiges Bild; mit ihr steht ein sauberes
   2x2 aus den drei kurzen Labeln und dem Richtungsknopf.

   PHASE 5 (A7): das zinsrepr-Segment ist von der 50%-Basis AUSGENOMMEN. Die alte
   Begruendung der Basis ("das breiteste Label passt in die halbe Zeile") galt fuer
   ein 105 px breites Label; das neue misst rund 350 px und faellt in einer 150 px
   breiten Halbspalte auf sechs Zeilen zusammen. Ueber die volle Breite braucht es
   zwei. Gesteuert ueber data-basis und nicht ueber :nth-child — die Reihenfolge
   der Segmente ist eine Anordnung, kein Vertrag.

   E52 (10.09.2026): "Anbieter" steht jetzt an ERSTER Stelle. Die Selektoren sind
   davon unberuehrt, der FLUSS nicht — die 50%-Basis teilt nach DOM-Position:
   unterhalb 30em steht jetzt Anbieter | Bestzins in Zeile 1, zinsrepr allein in
   Zeile 2, Spannenbreite (auf volle Breite gewachsen) in Zeile 3. Vorher: Bestzins
   allein, zinsrepr, Spannenbreite | Anbieter. Drei Zeilen wie zuvor; das Bild aus
   dem Absatz oben ("2x2") ist seit Phase 5 ohnehin Historie. Gerechnet, nicht
   gemessen (Review-Befund B3) — Messauftrag an den Live-VRT bei 375 px. */
@media (max-width: 30em) {
    .zk-sortierleiste { gap: 0.4rem 0.5rem; }
    .zk-sort-label,
    .zk-sort-segmente { flex: 1 1 100%; }
    .zk-sort-segment { flex: 1 1 calc(50% - 0.125rem); padding: 0.5em 0.6em; }
    .zk-sort-segment[data-basis="zinsrepr"] { flex-basis: 100%; }
}

/* ==========================================================================
   15) TEXTFASSUNG — Abschnitt aufgeloest (06.08.2026)

   Hier standen der Tabellen-Umschalter (.zk-fallback-schalter, .zk-fallback-toggle)
   und die Gegenregel .zk-fallback--sichtbar samt ihrer sechs Folgeregeln fuer die
   sichtbare Fassung der Tabelle. Alles davon ist auf Anwender-Entscheid entfernt:
   die Funktion "Zahlenwerte als Tabelle anzeigen" gibt es nicht mehr.

   WAS BLEIBT, steht in Abschnitt 9: die sr-only-Klammer .zk-fallback. Die Tabelle
   ist ab jetzt ausschliesslich Textfassung fuer Screenreader und Suchmaschinen und
   hat KEINEN sichtbaren Zustand mehr. Deshalb steht hier auch kein Rest: eine Regel
   fuer einen Zustand, den nichts mehr herstellt, liest sich beim naechsten Umbau
   als Beleg dafuer, dass es den Zustand noch gibt (Lehre aus der entfallenen
   caption-Regel, Phase 5/A4).
   ========================================================================== */

/* ==========================================================================
   16) FLIP-GRUNDLAGEN und prefers-reduced-motion (Phase 3)

   Die Engine setzt Transform und Transition INLINE (Vorbild-Muster) — CSS kann
   eine Inline-Transition nicht ohne !important ueberschreiben, und !important auf
   FLIP-Eigenschaften ist ausgeschlossen. Deshalb liegt hier nicht die Transition
   selbst, sondern ihre beiden Stellschrauben als Custom Properties. Eine
   Inline-Deklaration wie
       transition: transform var(--zk-flip-dauer) var(--zk-flip-kurve)
   loest die Werte weiterhin aus der Kaskade auf — damit greift die Media Query
   unten, ohne dass die Engine prefers-reduced-motion selbst abfragen muesste.
   Das ist ein VERTRAG mit ratenkredit-diagramm-race.js: wer die Dauer inline
   hartkodiert, haengt die Reduced-Motion-Regel ab.

   Kein globales "transition: none" (E32): diese Regel gilt AUSSCHLIESSLICH der
   FLIP-Bewegung der beiden umsortierten Container. Hover-, Fokus- und
   Farbuebergaenge der Bedienelemente bleiben davon unberuehrt — sie sind kurze
   Farbwechsel ohne Bewegung und nicht das, wovor die Einstellung schuetzt.

   0.001ms statt 0ms unter reduce: bei einer Dauer von exakt 0 feuert kein
   transitionend-Ereignis, und eine Engine, die daran ihr Aufraeumen haengt, bliebe
   mit Inline-Transforms stehen. 0.001ms ist fuer das Auge sofortig und feuert.

   .zk-leiter traegt schon in Abschnitt 5 position: relative; hier kommen nur die
   beiden Variablen dazu. Die Pflichtliste bekommt sie ebenfalls, weil die Engine
   sie parallel umsortiert (zwei Container, ein Bindeglied IDS).
   ========================================================================== */
.zk-leiter,
.zk-pflicht-liste {
    --zk-flip-dauer: 240ms;
    --zk-flip-kurve: cubic-bezier(0.22, 0.61, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
    .zk-leiter,
    .zk-pflicht-liste { --zk-flip-dauer: 0.001ms; }
}
/* OPTIONALER Haken fuer die Engine: setzt sie waehrend des Laufs
   data-flip="laeuft" auf den Container, bekommen nur die bewegten Zeilen eine
   Compositor-Ebene. Bewusst NICHT dauerhaft auf .zk-zeile — bis zu 29 Zeilen
   dauerhaft auf will-change kosten mehr, als sie an Ruckeln sparen. Bleibt das
   Attribut aus, aendert sich nichts. */
.zk-leiter[data-flip="laeuft"] > .zk-zeile,
.zk-pflicht-liste[data-flip="laeuft"] > .zk-pflicht-eintrag { will-change: transform; }

/* ==========================================================================
   16b) SORTIERMERKMAL SICHTBAR (Politur 13, 12.09.2026, E66)

   Zwei Attribute auf div.zk-buehne, beide gesetzt von der Engine
   (fuehreBedienungNach / pulsiereSortmerkmal), das erste zusaetzlich vom Core:
     data-sortbasis="anbieter|zins|zinsrepr|spanne"   aktive Sortier-BASIS
     data-sortpuls="laeuft"                           nur kurz nach einem Klick

   1. DAUERHAFT unter "Bestzins" (zins_asc UND zins_desc — die Basis ist der
      Bestzins, die Richtung aendert das Merkmal nicht): die LINKE Endkappe jedes
      Bandes wird zum Knopf — 0.36rem statt 0.14rem breit, rund, mit einer Kontur in
      Buehnenfarbe, die sie vom Bandbeginn trennt. Bewusst KEINE neue Farbe:
      --zk-cap bleibt, Mint gehoert der Raute (Abschnitt 6 zum Sprunglink sagt,
      warum die Palettenfarben belegt sind). Form und Kontur sind zwei
      nicht-farbliche Merkmale (P§8), und beide unterscheiden sich von der
      Randlagen-Kappe .zk-cap-kante (hoeher, 0.22rem breit): unter
      Bestzins-Sortierung ist eine Randlagen-Kappe hoeher UND ein Knopf — beides
      bleibt lesbar. Nur an Baendern (Anwender-Auftrag: "das linke Ende der
      Spanne"); Punkt- und Festzinszeilen haben kein linkes Ende.
      KEINE Geometrie der Zeile: die Kappe liegt absolut im Band, Breite und
      Schatten aendern keine Layout-Groesse — FLIP-sicher.

   2. PULS nach einem Sortierklick, je Basis auf dem Merkmal, nach dem sortiert
      wird: Anbietername (anbieter), linke Endkappe und Punkt (zins), Raute und
      Punkt (zinsrepr — Festzinszeilen tragen keine Raute, der Punkt IST dort der
      Wert), Band und Punkt (spanne). Ein Ring aus outline, der sich vom
      Element loest und verblasst — outline statt box-shadow, weil box-shadow an
      der Raute (.zk-raute-achsenrand, Abschnitt 8) und in der Hover-Kopplung
      (Abschnitt 20c) bereits belegt ist und sich nicht additiv animieren laesst;
      outline folgt dem rotate(45deg) der Raute und dem border-radius des Bandes.
      Der Anbietername ist Text: dort eine Flaeche, die verblasst (background plus
      box-shadow als Polster, weil ein Inline-Polster die Zeile umbraeche).
      START NACH DER FLIP-BEWEGUNG: animation-delay ist var(--zk-flip-dauer)
      (Abschnitt 16, vererbt von .zk-leiter) — der Ring steht waehrend der
      Bewegung (fill-mode both) und loest sich, sobald die Zeilen liegen. Unter
      prefers-reduced-motion ist der Delay damit automatisch 0.001ms, und die
      Keyframes wechseln auf eine Fassung OHNE Bewegung (nur Farbe verblasst) —
      kein animation: none, sonst fehlte das Merkmal genau den Nutzern, die es
      ueber die Bewegung nicht bekommen.
      Die Engine haelt das Attribut 2000 ms (Notbremse); die sichtbare Dauer ist
      --zk-puls-dauer und liegt darunter. Kein transform, kein Layout-Wert.
   ========================================================================== */
.zk-buehne { --zk-puls-dauer: 1100ms; }

/* 1. Dauerhafte Marke — (0,4,0) (Klasse + Attribut + zwei Klassen) schlaegt
   .zk-cap-kante (0,1,0), width gewinnt. */
.zk-buehne[data-sortbasis="zins"] .zk-band .zk-cap-lo {
    width: 0.36rem;
    border-radius: 0.18rem;
    box-shadow: 0 0 0 0.1rem var(--zk-grund);
}

/* 2. Puls. Der Ruhezustand definiert den unsichtbaren Ring, damit die Animation
   von einem festen Wert startet und ohne Sprung endet. */
.zk-buehne[data-sortbasis="anbieter"][data-sortpuls] .zk-anbieter {
    border-radius: 0.2rem;
    animation: zk-sortpuls-flaeche var(--zk-puls-dauer) ease-out var(--zk-flip-dauer) 1 both;
}
.zk-buehne[data-sortbasis="zins"][data-sortpuls] .zk-cap-lo,
.zk-buehne[data-sortbasis="zins"][data-sortpuls] .zk-punkt,
.zk-buehne[data-sortbasis="zinsrepr"][data-sortpuls] .zk-raute,
.zk-buehne[data-sortbasis="zinsrepr"][data-sortpuls] .zk-punkt,
.zk-buehne[data-sortbasis="spanne"][data-sortpuls] .zk-band,
.zk-buehne[data-sortbasis="spanne"][data-sortpuls] .zk-punkt {
    outline: 0.125rem solid transparent;
    animation: zk-sortpuls-ring var(--zk-puls-dauer) ease-out var(--zk-flip-dauer) 1 both;
}
@keyframes zk-sortpuls-ring {
    0%   { outline-color: var(--zk-puls-ring); outline-offset: 0.1rem; }
    35%  { outline-color: var(--zk-puls-ring); outline-offset: 0.2rem; }
    100% { outline-color: transparent;         outline-offset: 0.6rem; }
}
@keyframes zk-sortpuls-flaeche {
    0%   { background-color: var(--zk-puls-flaeche); box-shadow: 0 0 0 0.2rem var(--zk-puls-flaeche); }
    35%  { background-color: var(--zk-puls-flaeche); box-shadow: 0 0 0 0.2rem var(--zk-puls-flaeche); }
    100% { background-color: rgba(0,0,0,0);          box-shadow: 0 0 0 0.2rem rgba(0,0,0,0); }
}
@media (prefers-reduced-motion: reduce) {
    .zk-buehne[data-sortbasis="anbieter"][data-sortpuls] .zk-anbieter {
        animation-name: zk-sortpuls-flaeche-still;
    }
    .zk-buehne[data-sortbasis="zins"][data-sortpuls] .zk-cap-lo,
    .zk-buehne[data-sortbasis="zins"][data-sortpuls] .zk-punkt,
    .zk-buehne[data-sortbasis="zinsrepr"][data-sortpuls] .zk-raute,
    .zk-buehne[data-sortbasis="zinsrepr"][data-sortpuls] .zk-punkt,
    .zk-buehne[data-sortbasis="spanne"][data-sortpuls] .zk-band,
    .zk-buehne[data-sortbasis="spanne"][data-sortpuls] .zk-punkt {
        outline-offset: 0.15rem;
        animation-name: zk-sortpuls-ring-still;
    }
}
@keyframes zk-sortpuls-ring-still {
    0%, 55% { outline-color: var(--zk-puls-ring); }
    100%    { outline-color: transparent; }
}
@keyframes zk-sortpuls-flaeche-still {
    0%, 55% { background-color: var(--zk-puls-flaeche); box-shadow: 0 0 0 0.2rem var(--zk-puls-flaeche); }
    100%    { background-color: rgba(0,0,0,0);          box-shadow: 0 0 0 0.2rem rgba(0,0,0,0); }
}

/* ==========================================================================
   17) HOCHKONTRAST-HELL fuer die Bedienelemente aus Phase 3
   Zeichengleich zu den Bestands-Overrides im Inline-Block des Cores (dort
   .toggle-group/.toggle-btn Z. 1203-1207 und .filter-reset-btn Z. 1238-1239).
   Alle Overrides per Spezifitaet (ID + Klasse), nie !important, keine
   Geometrie-Aenderung. Der Fokusring wechselt hier auf #0070C0 — Mint auf weissem
   Grund traegt als Fokusmarkierung nicht; denselben Wechsel macht der Bestand
   bereits fuer .anpassen-filter-btn.
   Text und Rahmen der Textfassung: die Farbe kommt aus --text-primary, das
   vergleich.min.css unter kontrast-hell selbst tauscht (#fff -> #111). Eigene
   Hexwerte braucht hier nur, was der zentrale Kern nicht erreicht — die
   Trennlinien.
   ========================================================================== */
/* Rang-Badges in der hellen Palette. Zeichengleich zur Listenansicht, die dort
   #vergleich.kontrast-hell .produkt-rang { background: rgba(0,82,141,0.06) } faehrt.
   Die Schriftfarbe kommt in der Leiter aus --zk-typo-sek und im Pflichtblock aus den
   Dashboard-Variablen; beide sind in der hellen Palette bereits dunkel gesetzt, hier
   ist also nur der Grund nachzuziehen. */
#vergleich.kontrast-hell .zk-rang,
#vergleich.kontrast-hell .zk-pflicht-rang { background: rgba(0,82,141,0.06); }
#vergleich.kontrast-hell .zk-rang:empty,
#vergleich.kontrast-hell .zk-pflicht-rang:empty { background: none; }
/* Festzins-Banner in der hellen Palette (Politur 14, E68): Blau statt Mint, zeichengleich
   zur Liste (#vergleich.kontrast-hell a.produkt-badge.badge-festzins). Die Tabelle faehrt
   dort Weiss, weil ihre Badge-Zelle im Hell-Modus ein blaues Band bleibt — hier steht das
   Banner wie in der Liste auf hellem Grund: #00528D auf der 10-%-Blaufuellung ueber
   #F7F9FC rechnerisch 6,7:1. */
#vergleich.kontrast-hell .zk-badge-festzins { color: #00528D; border-color: rgba(0,82,141,0.30); background: rgba(0,112,192,0.10); }
#vergleich.kontrast-hell .zk-sort-label { color: #003A66; }
#vergleich.kontrast-hell .zk-sort-segmente { background: rgba(0,82,141,0.06); }
#vergleich.kontrast-hell .zk-sort-segment { color: #003A66; }
#vergleich.kontrast-hell .zk-sort-segment:hover { background: rgba(0,82,141,0.08); color: #003A66; }
#vergleich.kontrast-hell .zk-sort-segment.active { background: #0070C0; color: #fff; }
#vergleich.kontrast-hell .zk-sort-richtung { color: #003A66; background: rgba(0,82,141,0.08); border-color: rgba(0,82,141,0.30); }
#vergleich.kontrast-hell .zk-sort-richtung:hover { background: rgba(0,82,141,0.15); }
#vergleich.kontrast-hell .zk-sort-segment:focus-visible,
#vergleich.kontrast-hell .zk-sort-richtung:focus-visible { outline-color: #0070C0; }
/* Die drei Hell-Regeln fuer den Tabellen-Umschalter und die sichtbare Textfassung
   sind am 06.08.2026 mit Abschnitt 15 entfallen — die Tabelle hat keinen sichtbaren
   Zustand mehr, ihre Trennlinien werden in keiner Palette gezeichnet. */

/* ==========================================================================
   18) SCROLL-LOCK DES PANEL-OVERLAYS (Phase 3)

   Die Engine setzt beim Oeffnen des Panels die Klasse zk-overlay-locked auf
   <html> und nimmt sie beim Schliessen zurueck (ratenkredit-diagramm-race.js,
   oeffnePanel/schliessePanel). Ohne Gegenstueck im CSS ist die Klasse wirkungslos
   und der Hintergrund scrollt unter dem offenen Panel weiter.

   NUR AM BODY (Politur 16, 12.09.2026, E72). Bis dahin stand die Deklaration auf
   html UND body, mit der Begruendung, je nach Bestands-Stylesheet koenne eines von
   beiden den Scroll-Kontext tragen. Gemessen am 12.09.2026 (Live, 1200 x 800):
   style.css gibt html UND body height: 100% (je 800 px). Traegt dann auch body
   overflow: hidden, propagiert sein Wert nicht mehr an den Viewport (html ist schon
   hidden), body wird selbst zum geklemmten Container, html.scrollHeight faellt von
   8671 auf 800 px — und der Viewport springt beim OEFFNEN des Panels auf 0
   (1440 -> 0 px; Schliessknopf, Esc und Backdrop gleichermassen; Anwender-Befund
   "HypoVereinsbank, 1.440 Pixel verloren"). Einzeln gesetzt haelt sowohl html-only
   als auch body-only die Position (1440 bleibt, scrollHeight 8671) UND blockiert
   das Mausrad (gemessen 0 px Bewegung bei 400 px Rad). body-only, weil die
   Brokerage-Schwester dieselbe Form fuehrt (html.kb-overlay-locked body). Die
   Kreditkarte-Schwester hat denselben Sprung ueber position: fixed am body plus
   JS-gesetztem top geloest und den Fehler dem Wurzelelement zugeschrieben — der
   Mechanismus ist die KOMBINATION, nicht html allein. Wer hier wieder beide
   Selektoren eintraegt, baut den Sprung wieder ein.

   Diese eine Regel entstand in Phase 3, weil die Engine die Klasse schon damals
   setzte — eine Klasse ohne Regel ist eine stille Zusage, die niemand einloest.
   Die restliche Panel-OPTIK steht seit Phase 4 in ABSCHNITT 20 weiter unten
   (Overlay, Blau-Glas-Panel, Reiter, Bottom-Sheet, zweite Palette).
   ========================================================================== */
html.zk-overlay-locked body { overflow: hidden; }

/* ==========================================================================
   19) UEBERGANG STILLLEGEN BEIM WIEDERHERSTELLEN DES FILTER-OVERLAYS
        (Phase 3, Nachbesserung 30.07.2026)

   Seit der Nachbesserung tauscht ein Filterwechsel .vergleich-dashboard als
   Ganzes aus — und das "weitere Filter"-Overlay liegt INNERHALB dieser
   Swap-Zone (diagramm-ratenkredit-core.inc.php Z. 1515). Der Knoten ist nach
   dem Tausch also frisch und zu; die Engine macht ihn sofort wieder auf
   (stelleOberflaecheHer). Ohne diese Regel spielte dabei jedes Mal die
   Einblend-Animation erneut: Backdrop von opacity 0 und Panel aus
   translateY(-0.75em) — bei jedem einzelnen Haekchen ein sichtbares Flackern,
   obwohl aus Nutzersicht gar nichts auf- oder zugeht.

   Die Uebergaenge selbst stehen im Inline-Block des Cores (.anpassen-backdrop
   und .anpassen-panel, je 125ms). Sie werden hier fuer die Dauer eines Frames
   ueber SPEZIFIZITAET ausgehebelt, nicht ueber !important: 0,3,0 gegen die
   0,1,0 der Core-Regeln. Die Engine setzt die Klasse, erzwingt einen Reflow und
   nimmt sie sofort wieder ab — im Ruhezustand ist diese Regel also nie aktiv,
   und ein regulaeres Oeffnen per Klick behaelt seine Animation.
   ========================================================================== */
.anpassen-overlay.zk-ohne-uebergang .anpassen-backdrop,
.anpassen-overlay.zk-ohne-uebergang .anpassen-panel { transition: none; }

/* ==========================================================================
   20) DETAILPANEL (Phase 4, E3/E32/E43/E44 — Geometrie neu gefasst mit E53/E56,
       Politur 10.09.2026)

   Bis Phase 3 hatte .zk-panel* keine einzige Regel: die Huelle stand im Core, die
   Engine oeffnete sie, und ein geoeffnetes Overlay rendete als gewoehnlicher Block
   im Textfluss. Das faellt live nicht auf, weil es bis Phase 4 keinen Ausloeser
   gab (Recon A.8/A.9). Hier entsteht die gesamte Optik.

   GEOMETRIE SEIT E53: ein RECHTS EINFAHRENDES SEITENPANEL nach dem Vorbild des
   Festgeld-DE-Diagramms (.zg-karte) — volle Viewport-Hoehe, 30rem breit, buendig
   an der rechten Kante, Mint-Kante und Schatten nach links. Bis dahin war es ein
   zentriertes Fenster mit Rundum-Rahmen und 4rem Aussenpolster. Die Werte sind
   1:1 uebernommen (Breite, Polster 4.65em/2em/2em, Glas, Kantenfarbe, Schatten,
   font-size/line-height), damit die beiden kreativen Ansichten dieselbe
   Panel-Sprache sprechen. Das Panel ist position: absolute IM Overlay (das
   Overlay ist fixed) — es bleibt damit sein eigener Containing Block fuer den
   Schliessknopf und braucht kein eigenes position: fixed.

   DIE MODAL-MECHANIK BLEIBT UNVERAENDERT und ist der Unterschied zum Vorbild: Das
   Festgeld-Panel ist hover-basiert, nicht-modal und hat deshalb GAR KEINEN
   Backdrop. Dieses hier wird per Klick geoeffnet, traegt aria-modal, Fokusfalle,
   Esc-Zweig und den Scroll-Lock html.zk-overlay-locked — es braucht den Backdrop
   als klickbare Schliessflaeche und als optische Abtrennung. Seine Farbe ist
   deshalb NICHT vom Festgeld-Panel geliehen (das hat keine), sondern von den
   modalen Haus-Schwestern: rgba(9, 30, 48, 0.5) wie Tagesgeld-DE-Skyline und
   Brokerage-Kurvenblick, hell rgba(0, 26, 48, 0.35). Der frueher hier stehende
   Neutralwert rgba(0,0,0,0.55) war ein Eigenweg ohne Vorbild.

   SICHTBARKEIT laeuft ueber das vorhandene Attributpaar der Engine und wird NICHT
   ersetzt: sie nimmt beim Oeffnen hidden weg und setzt data-offen="1", beim
   Schliessen umgekehrt (ratenkredit-diagramm-race.js, oeffnePanel/schliessePanel).
   hidden bleibt der Garant fuer den Fall, dass dieses Stylesheet nicht laedt —
   dann greift die UA-Regel [hidden]{display:none}. Die Regel unten wiederholt sie
   trotzdem ausdruecklich, weil eigene display-Regeln auf .zk-panel-overlay die
   UA-Regel sonst schlagen wuerden.

   EINBLENDUNG ALS ANIMATION, NICHT ALS TRANSITION — und das ist kein Geschmack:
   Die Engine nimmt hidden weg und setzt data-offen im SELBEN synchronen Block.
   Der Browser berechnet dazwischen keinen Stil, es gibt also keinen Startzustand,
   von dem aus eine transition laufen koennte — sie fiele stumm aus. Eine
   CSS-Animation braucht keinen vorherigen Renderzustand und spielt zuverlaessig,
   sobald das Element zum ersten Mal dargestellt wird. Genau deshalb kann das
   Vorbild seine Slide als transition fahren (die .zg-karte steht dauerhaft im DOM
   und wird nur per Klasse verschoben) und dieses Panel nicht. Die RICHTUNG ist
   mit E53 dieselbe geworden: translateX(100%) -> none in 280ms
   cubic-bezier(0.22, 0.61, 0.36, 1), das Timing des Vorbilds. Das
   prefers-reduced-motion-Pendant dieser Achse liegt auf animation, waehrend das
   Pendant der FLIP-Achse (Abschnitt 16) auf --zk-flip-dauer liegt: zwei Achsen,
   zwei eigene Regeln, wie E32 es verlangt. Die reduzierte Variante zeigt das
   Panel an seiner ENDposition, statt nur den Uebergang abzuschalten.

   Z-INDEX: Overlay 200 / Panel 201. Das Filter-Overlay des Cores liegt bei
   100/101/102; das Detailpanel muss darueber liegen, weil beide gleichzeitig
   offen sein koennen. Der Schliessknopf traegt im Core z-index: 102 — das wirkt
   innerhalb des Stapelkontexts, den .zk-panel mit position und z-index aufmacht,
   und bleibt damit korrekt oben.

   DER SCHLIESSKNOPF WIRD SEIT E56 HIER GESTALTET — der Absatz an dieser Stelle
   sagte bis zum 10.09.2026 das Gegenteil, und der Grund dafuer ist entfallen:
   Er lautete, .panel-close-btn sei ein Bestandsname, den sich BEIDE Panels teilen
   (Filter-Panel und Detailpanel), und wer ihn hier anfasse, aendere zwei Panels
   auf einmal. Das stimmt fuer den Klassennamen — nicht mehr fuer den Selektor:
   Der Knopf des Detailpanels traegt jetzt ZUSAETZLICH die Zweitklasse
   .zk-panel-close (Core, #zkPanelCloseBtn). Der Selektor unten
   .zk-panel-overlay .zk-panel .zk-panel-close traegt damit 0,3,0 und schlaegt
   sowohl die Inline-Regel .panel-close-btn des Cores als auch die zentrale Regel
   der vergleich.min.css (beide 0,1,0). Der Knopf des FILTER-Panels (#panelCloseBtn)
   traegt die Zweitklasse NICHT und bleibt unberuehrt — das ist die ganze Trennung.
   ZWEI Fallen dabei, beide unten am Regelblock ausbuchstabiert: die Core-Regel
   setzt die Ecken EINZELN (border-top-right-radius / border-bottom-left-radius),
   und sie loescht auf :focus die outline.
   Er ist position: absolute an der Panel-Oberkante — deshalb hat das Panel oben
   mehr Polster als unten (4.65em gegen 2em) und ist selbst positioniert, damit
   "absolute" sich auf das Panel bezieht.
   ========================================================================== */

/* --- Overlay + Backdrop ------------------------------------------------- */
.zk-panel-overlay[hidden] { display: none; }
.zk-panel-overlay {
    position: fixed;
    top: 0; right: 0; bottom: 0; left: 0;
    z-index: 200;
    /* E53: KEIN Flex-Zentrieren mehr und kein Aussenpolster. Das Panel dockt sich
       selbst per position: absolute an die rechte Kante; ein Flex-Container
       daherum haette nur eine zweite Wahrheit ueber seine Lage erzeugt. */
    display: block;
    padding: 0;
    /* KEIN backdrop-filter auf dem Overlay (E32 woertlich) — er steht allein am
       Panel. Ein Filter hier legte den Weichzeichner ueber die ganze Seite und
       machte aus dem Backdrop eine zweite Milchglasscheibe. */
    overflow: hidden;
}
.zk-panel-overlay .zk-panel-backdrop {
    /* Absolut positioniert wie das Panel selbst. Klickbar bleibt er — die Engine
       bindet ihn als Schliess-Zweig; er liegt ohne z-index unter dem Panel (201).
       FARBE: siehe Abschnittskopf. Der Wert stammt von den modalen
       Haus-Schwestern (Tagesgeld-DE-Skyline, Brokerage-Kurvenblick), nicht vom
       Festgeld-Panel — das ist hover-basiert und hat gar keinen Backdrop. */
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    background: rgba(9, 30, 48, 0.5);
}

/* --- Panel (Geometrie 1:1 nach .zg-karte, Festgeld DE — E53) ------------- */
.zk-panel-overlay .zk-panel {
    position: absolute;
    z-index: 201;
    top: 0; right: 0; bottom: 0; left: auto;
    height: 100%;
    width: 30rem;                           /* E3/E53: 30rem am Desktop */
    max-width: 100%;
    box-sizing: border-box;
    margin: 0;
    /* 4.65em Kopfzone: der Inhalt beginnt UNTER dem Schliessknopf (top 1em,
       Hoehe 2.4rem). Deshalb braucht der Titel keinen Rechtsabstand mehr —
       keine Textzeile liegt auf Knopfhoehe. Uebernommen aus CT-0319 des
       Vorbilds, wo derselbe Rechtsabstand lange Anbieternamen in einen
       Waisen-Umbruch getrieben hatte. */
    padding: 4.65em 2em 2em;
    background: rgba(9, 87, 143, 0.92);     /* E3: Blau-Glas */
    backdrop-filter: blur(1.25em);
    -webkit-backdrop-filter: blur(1.25em);
    border: none;
    border-left: 0.0625em solid rgba(76, 181, 160, 0.45);   /* E53: Mint-Kante links */
    border-radius: 0;
    box-shadow: -0.5em 0 2em rgba(0, 26, 48, 0.4);
    display: flex;
    flex-direction: column;
    font-size: 0.9rem;
    line-height: 1.35;
    color: #ffffff;                         /* E3: weisse Typo, 7,34:1 */
}

/* --- Schliessknopf (E56) -------------------------------------------------
   Werte 1:1 aus .zg-karte-close (Festgeld DE), einschliesslich right: 1.8rem —
   das fluchtet den Knopf mit der Inhaltsspalte, weil das Panel rechts 2em
   Polster bei 0.9rem Grundschrift traegt (2 x 0.9 x 16 = 28,8 px = 1,8rem).

   DER SELEKTOR TRAEGT 0,3,0 UND MUSS ES: er schlaegt damit die 0,1,0 der
   Core-Inline-Regel .panel-close-btn und die 0,1,0 der zentralen Regel in
   vergleich.min.css. Der Filter-Panel-Knopf traegt .zk-panel-close nicht und
   bleibt unberuehrt.

   ZWEI FALLEN AUS DER CORE-REGEL, die diesen Block laenger machen, als er
   aussehen muesste:
     1. Sie setzt die Ecken EINZELN (border-top-right-radius: var(--radius-md);
        border-bottom-left-radius: 0). Eine Kurzform border-radius hier
        ueberschreibt beide — deshalb steht sie da und nicht nur eine Ecke.
        Aus demselben Grund sind top/right/width/height/padding/font-size/
        line-height/background/color/border/display/transition ALLE ausdruecklich
        gesetzt: was hier fehlte, schiene aus der Core-Regel durch und ergaebe
        eine halb uebernommene Optik.
     2. Sie loescht .panel-close-btn:hover, .panel-close-btn:focus { outline: none }.
        Die :focus-visible-Regel unten traegt 0,4,0 und gewinnt — bei Maus-Fokus
        (ohne :focus-visible) bleibt outline: none dagegen gewollt stehen.
   Der :focus-Zweig der Core-Regel setzt ausserdem einen GRAUEN Grund
   (rgba(61,69,76,0.85)); deshalb nimmt die Hover-Regel unten :focus mit auf,
   sonst schlaege der Knopf bei Tastaturfokus in die Bestandsfarbe um.
   z-index: 102 aus der Core-Regel bleibt bewusst stehen — er wirkt im
   Stapelkontext des Panels und haelt den Knopf ueber dem Inhalt. */
.zk-panel-overlay .zk-panel .zk-panel-close {
    position: absolute;
    top: 1em;
    right: 1.8rem;
    width: 2.4rem;
    height: 2.4rem;
    padding: 0;
    border: 0;
    border-radius: 0.5em;
    background: rgba(255, 255, 255, 0.16);
    color: #ffffff;                 /* 5,07:1 auf dem gemischten Knopfgrund */
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 130ms ease;
}
.zk-panel-overlay .zk-panel .zk-panel-close:hover,
.zk-panel-overlay .zk-panel .zk-panel-close:focus {
    background: rgba(255, 255, 255, 0.30);
    color: #ffffff;
}
.zk-panel-overlay .zk-panel .zk-panel-close:focus-visible {
    outline: 0.125em solid #ffffff;
    outline-offset: 0.125em;
}
/* HIER STAND BIS ?v=15 EINE MEDIA-REGEL FUER DAS BAND 48em < Breite <= 52em
   (768-832 px), die den Knopf dort auf 2.75rem (44 px) haertete. Sie ist mit E57
   ENTFALLEN (Anwender-Entscheid 10.09.2026 nach dem Upload): Massstab ist die
   Paritaet zum Vorbild .zg-karte-close (Festgeld DE), nicht das Core-Touch-Mass.
   Oberhalb 48em gilt damit durchgehend die 2.4rem der Basisregel oben (38,4 px),
   unterhalb das Sheet-Mass 2.75rem aus dem 48em-Block weiter unten.

   ZWEI DINGE, DIE MAN HIER NICHT VERWECHSELN DARF:
     1. Die Core-INLINE-Regel .panel-close-btn setzt in genau diesem Band nach wie
        vor 2.75rem (Haus-Regel CT-0220/CT-0234). Sie ist NICHT diese Datei, bleibt
        unangetastet und verliert mit 0,1,0 gegen die 0,3,0 der Basisregel — genau
        deshalb wirkt ihr Wegfall hier ueberhaupt.
     2. Wer im Band wieder 44 px misst, hat entweder E57 zurueckgedreht oder eine
        Regel mit hoeherer Spezifitaet ergaenzt. Sollwert 800 px: 38,4 px. */

/* Der SCROLL liegt auf dem Body, nicht auf dem Panel. Waere er am Panel, scrollte
   der absolut positionierte Schliessknopf mit aus dem Bild — bei drei Reitern mit
   dem vollstaendigen § 17-Text ist das kein Randfall. Das unterscheidet die
   Konstruktion vom Vorbild, das den Scroll auf der Karte selbst fuehrt und den
   Knopf dort per position: fixed haelt. min-height: 0 ist in einer Flex-Spalte
   Pflicht, sonst weigert sich das Kind zu schrumpfen und das Panel waechst ueber
   seine Hoehe hinaus.

   FLEX-SPALTE SEIT E53: Der Body ist selbst eine Spalte, damit sich der
   Panel-Fuss per margin-top: auto ans untere Ende haengen kann (Muster
   Festgeld/Tagesgeld). Die Kette dazu hat vier Glieder und jedes muss stimmen:
     .zk-panel-body   display: flex / column
     > *              flex: 0 0 auto   (keine Stauchung im Scroll-Fall)
     .zk-detail       flex: 1 0 auto + eigene Spalte  (fuellt den Body aus)
     .zk-detail-fuss  margin-top: auto (unten am Regelblock "Panel-Fuss")
   Bei KURZEM Inhalt ankert der CTA damit am Panel-Ende, bei LANGEM folgt er dem
   Inhalt im Scroll — dann loest auto zu 0 auf. .zk-detail steht mit 0,3,0 ueber
   der > *-Regel (0,2,0) und behaelt sein flex-grow. */
.zk-panel-overlay .zk-panel-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
}
.zk-panel-overlay .zk-panel-body > * { flex: 0 0 auto; }
/* Titel-Metrik nach .zg-dk-bank des Vorbilds. KEIN Rechtspolster mehr: der
   Schliessknopf steht seit E53 ueber der Kopfzone des Panels (padding-top
   4.65em), nicht mehr neben der ersten Textzeile. Im Bottom-Sheet kehrt das
   Polster zurueck — dort sitzt der Knopf wieder neben dem Titel. */
.zk-panel-overlay .zk-panel-titel {
    flex: 0 0 auto;
    margin: 0 0 0.75rem;
    padding: 0;
    font-size: 1.15rem;
    font-weight: 700;
    font-style: normal;
    line-height: 1.35;
    color: #ffffff;
}

/* --- Gescopte Leak-Resets ------------------------------------------------
   Pflicht, nicht Vorsichtsmassnahme (E32). Gemessen am 31.07.2026 gegen
   Upload\DE\vergleich.min.css und Upload\DE\style.css:
     - style.css fuehrt  h3{font-style:italic;margin:75px 0 0;padding:0 5%;
       color:#f0f0ff;font-size:1em;line-height:1.8em;font-weight:600}  UNSCOPED.
       75px Aussenabstand im Panel waeren sofort sichtbar.
     - style.css fuehrt  ul{margin:2px 0 6px 5%}  und  li{list-style:none}
       unscoped. Der Panel-Inhalt ist heute div-basiert; die Resets stehen
       trotzdem, weil der Core seine Feldgruppen jederzeit auf <ul> umstellen kann
       und der Fehler dann still waere.
     - aside und aside p tragen in style.css Breite, Float, Hintergrund, Hoehe und
       Aussenabstaende. Das Panel ist ein <div> (E32), die Reiterflaechen sind
       <section> — der Reset steht als Absicherung gegen kuenftiges Markup.
     - BARE <section>-REGELN GIBT ES NICHT: gemessen in vergleich.min.css sind die
       einzigen zwei section-Treffer .vergleich-dashboard .filter-section, also
       klassen- UND dashboard-gescoped; das Panel liegt ausserhalb der
       .vergleich-dashboard. In style.css: null Treffer. display: block steht
       trotzdem, damit die Reiterflaechen nicht von einer spaeteren Bestandsregel
       auf flex oder grid gezogen werden.
     - [hidden] ist in BEIDEN Bestandsdateien unbelegt (je 0 Treffer) — die
       UA-Regel traegt also. Sie wird je Namensraum trotzdem wiederholt, weil
       eigene display-Regeln sie sonst schlagen. */
.zk-panel-overlay .zk-panel * { box-sizing: border-box; }
.zk-panel-overlay .zk-panel p,
.zk-panel-overlay .zk-panel h3 {
    margin: 0;
    padding: 0;
    font: inherit;
    color: inherit;
}
.zk-panel-overlay .zk-panel ul,
.zk-panel-overlay .zk-panel ol,
.zk-panel-overlay .zk-panel li { margin: 0; padding: 0; list-style: none; }
.zk-panel-overlay .zk-panel aside,
.zk-panel-overlay .zk-panel aside p {
    width: auto;
    height: auto;
    float: none;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
}
.zk-panel-overlay .zk-panel section { display: block; margin: 0; padding: 0; background: none; }
.zk-panel-overlay .zk-panel .icon { position: static; margin: 0; font-size: inherit; }

/* --- Einblendung und prefers-reduced-motion (Achse "Panel-Slide") -------- */
/* E53: Slide von RECHTS statt Einschweben von oben. Kein opacity-Anteil mehr —
   das Vorbild schiebt seine Karte rein und blendet sie nicht ein; ein
   gleichzeitiges Aufblenden liesse die Mint-Kante flackern. Der Backdrop behaelt
   seinen Fade und zieht auf dieselbe Dauer mit, damit Scrim und Panel gemeinsam
   ankommen. Das Sheet-Pendant bleibt inhaltlich, wie es war. */
@keyframes zk-panel-ein {
    from { transform: translateX(100%); }
    to   { transform: none; }
}
@keyframes zk-panel-ein-sheet {
    from { opacity: 0; transform: translateY(100%); }
    to   { opacity: 1; transform: none; }
}
@keyframes zk-backdrop-ein {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.zk-panel-overlay[data-offen] .zk-panel { animation: zk-panel-ein 280ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.zk-panel-overlay[data-offen] .zk-panel-backdrop { animation: zk-backdrop-ein 280ms ease-out both; }

@media (prefers-reduced-motion: reduce) {
    /* Eigenes Pendant DIESER Achse (E32). Nicht nur "animation: none": ohne die
       beiden Endwerte stuende das Panel bei einer teilweise angewandten Animation
       einen Frame ausserhalb des Bildes. Endposition ausdruecklich hinschreiben. */
    .zk-panel-overlay[data-offen] .zk-panel,
    .zk-panel-overlay[data-offen] .zk-panel-backdrop {
        animation: none;
        opacity: 1;
        transform: none;
    }
}

/* --- Reiter (WAI-ARIA-Muster, Metrik in rem — E32) ----------------------- */
/* Zweites und drittes Glied der Fuss-Anker-Kette (siehe .zk-panel-body oben).
   .zk-detail fuellt den Body aus und ist selbst eine Spalte; der Reiter-Block
   bleibt inhaltshoch, damit allein der Fuss den Rest einnimmt. */
.zk-panel-overlay .zk-panel .zk-detail {
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
}
.zk-panel-overlay .zk-panel .zk-reiter-block { display: block; flex: 0 0 auto; }
.zk-panel-overlay .zk-panel .zk-reiterleiste {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin: 0 0 0.85rem;
    border-bottom: 0.0625rem solid rgba(169, 246, 219, 0.35);
}
/* Reiter-Reset: derselbe Satz Gruende wie beim Zeilen-Button (Recon F7), nur ohne
   Grid. Die Mindesthoehe 2,75rem ist das Trefferflaechen-Mass der Bestands-
   Checkboxen (.sidebar-filter-checkbox im Core), damit die Reiter auf dem
   Bottom-Sheet nicht kleiner ausfallen als alles andere Bedienbare. */
.zk-panel-overlay .zk-panel .zk-reiter {
    -webkit-appearance: none;
    appearance: none;
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    margin: 0;
    padding: 0.4rem 0.7rem;
    border: 0;
    border-bottom: 0.1875rem solid transparent;
    background: none;
    color: #C3D3E2;                 /* 4,80:1 */
    font: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.3;
    text-align: center;
    white-space: nowrap;
    cursor: pointer;
}
.zk-panel-overlay .zk-panel .zk-reiter:hover { color: #ffffff; }
/* Der aktive Reiter ist NICHT allein ueber Farbe ausgezeichnet: er traegt zwei
   Merkmale, die auch ohne Farbwahrnehmung tragen — einen Balken an der Unterkante
   (vorhanden gegen nicht vorhanden) und eine Grundflaeche (ebenso). Die
   Schriftstaerke bleibt bei 600, statt auf 700 zu springen: ein Wechsel der
   Staerke aendert die Textbreite und liesse die Reiterleiste bei jedem Wechsel
   nachrutschen. Beide Zustaende, aria-selected und die Klasse .active, weil der
   Kontrakt beide setzt und keiner allein verlaesslich ist. */
.zk-panel-overlay .zk-panel .zk-reiter.active,
.zk-panel-overlay .zk-panel .zk-reiter[aria-selected="true"] {
    color: #ffffff;
    background: rgba(169, 246, 219, 0.12);
    border-bottom-color: #A9F6DB;   /* 5,90:1 */
    border-radius: 0.25rem 0.25rem 0 0;
}
.zk-panel-overlay .zk-panel .zk-reiter:focus-visible {
    outline: 0.125rem solid #A9F6DB;
    outline-offset: -0.125rem;      /* nach INNEN, sonst kappt die Leiste den Ring */
}
.zk-panel-overlay .zk-panel .zk-reiter-label { display: inline-block; }

/* Reiterflaechen verstecken sich per hidden, NICHT per Klasse (Recon F3):
   fokusZiele() der Engine filtert ueber offsetParent !== null, und das trifft nur
   bei display: none zu. .tab-panel waere hier doppelt falsch — die Bestandsregel
   ist auf .vergleich-dashboard gescoped, ausserhalb derer das Panel liegt, und
   vergleich.min.js bindet auf .details-tab einen zweiten Controller mit
   stopPropagation() (Recon F2). */
.zk-panel-overlay .zk-panel .zk-reiterflaeche { display: block; }
.zk-panel-overlay .zk-panel .zk-reiterflaeche[hidden] { display: none; }

/* --- Inhalt der Flaechen ------------------------------------------------- */
.zk-panel-overlay .zk-panel .zk-feldliste { display: block; margin: 0 0 0.6rem; }
.zk-panel-overlay .zk-panel .zk-feld {
    display: flex;
    flex-wrap: wrap;
    gap: 0.1rem 0.6rem;
    padding: 0.4rem 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.zk-panel-overlay .zk-panel .zk-feld:last-child { border-bottom: 0; }
.zk-panel-overlay .zk-panel .zk-feld-name {
    flex: 0 0 10rem;
    max-width: 100%;
    color: #C3D3E2;                 /* 4,80:1 */
    font-size: 0.78rem;
    line-height: 1.45;
}
.zk-panel-overlay .zk-panel .zk-feld-wert {
    flex: 1 1 9rem;
    min-width: 0;
    color: #ffffff;
    font-size: 0.82rem;
    line-height: 1.45;
}
/* Politur 13 (E65): die Kopfzeile des Reiters "alle Zinssaetze" liest sich als Satz —
   "bei Nettodarlehensbetrag EUR 10.000 bis EUR 19.999". Der Feldname nimmt dafuer
   seine natuerliche Breite statt der 10rem-Spalte: "bei Nettodarlehensbetrag" ist
   in 0.78rem breiter als 10rem und braeche dort in zwei Zeilen um (gemessen
   12.09.2026 auf der Live-Seite: 36,19 px statt 19,03 px Hoehe). Farben und
   Schnitt bleiben die der Feldliste (Name sekundaer, Wert weiss); (0,4,0) schlaegt
   die 10rem-Regel (0,3,0) und die Sheet-Regel flex: 1 1 100% (Abschnitt 20, <= 48em).
   Der WERT bekommt in dieser Zeile ebenfalls seine natuerliche Basis (auto statt
   9rem): nur so springt er im Sheet als GANZES in die naechste Zeile, wenn er neben
   dem Namen nicht mehr passt — mit 9rem Basis blieb er daneben und brach mitten im
   Betrag um ("EUR 10.000 bis EUR / 19.999", gemessen 12.09.2026 bei 375 px: Wert
   168,7 px breit, 38,06 px hoch). flex-wrap steht am .zk-feld. */
.zk-panel-overlay .zk-panel .zk-feld-satz .zk-feld-name { flex: 0 0 auto; }
.zk-panel-overlay .zk-panel .zk-feld-satz .zk-feld-wert { flex: 1 1 auto; }

/* Beschriftung ueber dem Beispieltext (E58, A3 vom 10.09.2026): "Repraesentatives
   Beispiel (§ 17 PAngV)". Sie sagt, WAS der Block darunter ist — bis ?v=15 stand der
   Beispieltext ohne jede Ansage in der Flaeche.

   OPTIK = .zk-feld-name (0.78rem / 1.45 / #C3D3E2, hell #3C4F5E in Abschnitt 21).
   Der Anwender hat die Feldnamen-Optik gewaehlt und nicht das Name/Wert-Raster
   eines .zk-feld: der Beispieltext ist zu lang fuer eine Wertspalte. KEIN <h3> —
   in den Flaechen stehen keine Ueberschriften (Phase-4-Regel), das Markup liefert
   ein <p class="zk-beispiel-titel">.

   DREI KLASSEN IM SELEKTOR SIND PFLICHT, NICHT STIL: der gescopte Leak-Reset
   .zk-panel-overlay .zk-panel p (0,2,1, weiter oben) setzt margin: 0 und
   font: inherit. Ein Ein-Klassen-Selektor (0,1,0) verloere gegen ihn unabhaengig
   von der Reihenfolge — margin-bottom UND Schriftgrad waeren tot. Das ist die
   Falle des ?v=12-Satzes (.zk-legende-auswahl gegen .zk-legende p), hier vorab
   geprueft: im Panel adressiert nur dieser eine Reset ein bares p. */
.zk-panel-overlay .zk-panel .zk-beispiel-titel {
    margin: 0 0 0.2rem;
    font-size: 0.78rem;
    line-height: 1.45;
    color: #C3D3E2;                 /* 4,80:1, wie .zk-feld-name */
}

/* Der wortgleiche § 17-Pflichtblock-Text (E41). Er kommt fertig transformiert aus
   $zkPflichtangaben und traegt HTML; .beispiel-effzins und .beispiel-pa stammen aus
   den Pipeline-Transformatoren. Optik zeichengleich zum Pflichtblock unterhalb der
   Leiter (Abschnitt 12) — inklusive der dort begruendeten Abweichung, dass auch
   "p. a." die volle Textfarbe traegt statt --text-muted: in einem Pflichtblock ist
   auch der Periodenzusatz Pflichttext. Eine dritte Optik derselben Pflichtangabe
   waere Cross-View-Drift. ACHTUNG, zwei aehnliche Namen: .zk-beispieltext ist der
   Panel-Text (Kontrakt §4), .zk-beispiel-text der des Pflichtblocks (Abschnitt 12). */
.zk-panel-overlay .zk-panel .zk-beispieltext {
    margin: 0 0 0.5rem;
    font-size: 0.78rem;
    line-height: 1.55;
    color: #ffffff;
}
.zk-panel-overlay .zk-panel .zk-beispieltext .beispiel-effzins { font-weight: inherit; color: #ffffff; }
.zk-panel-overlay .zk-panel .zk-beispieltext .beispiel-pa { font-size: 0.66rem; font-weight: 500; color: #ffffff; }
.zk-panel-overlay .zk-panel .zk-beispieltext em { font-style: italic; }

/* Herkunftssatz der Raute (E10/E42). Bewusst als abgesetzter Block und NICHT als
   kleingedruckte Fussnote: er entscheidet, ob der § 17-Wert aus dem Beispiel der
   Bank stammt oder gar nicht vorliegt — das ist die Aussage, wegen der E42 drei
   Code-Zweige verlangt, nicht Beiwerk.

   ABGESETZT HEISST SEIT E62: allein ueber die hinterlegte Flaeche. Die Mint-Kante
   links ist entfallen (Begruendung an .zk-modushinweis). Dafuer traegt der Block
   mehr Luft — innen +0.3em oben und unten, aussen +1em oben und unten. Beides als
   calc() auf den Bestandswerten, damit die rem-Metrik der Datei erhalten bleibt und
   der em-Anteil mit dem Schriftgrad dieses Absatzes mitwaechst.

   ZWEI Gegner, nicht einer — beide gemessen, nicht angenommen:
     - der eigene Leak-Reset .zk-panel-overlay .zk-panel p (0,2,1) haette margin UND
       padding getoetet (Falle des ?v=12-Satzes); dagegen genuegten schon 0,3,0.
     - style.css fuehrt aber #vergleich p { padding: 0 5px 0 4px; line-height: 1.4em }
       mit (1,0,1) — und DAS schlug auch 0,3,0. Gerendert standen hier deshalb seit
       Phase 4 null Pixel Polster oben und unten (CDP-Messung 10.09.2026), waehrend
       die Datei 0.5rem behauptete; die margin-Werte griffen, weil der Bestand keine
       setzt. Mit #vergleich davor traegt der Selektor (1,3,0) und gewinnt beides.
       Kein !important — das Projekt loest solche Faelle ueber den Selektor. */
#vergleich .zk-panel-overlay .zk-panel .zk-repr-hinweis {
    margin: 1em 0 calc(0.7rem + 1em);
    padding: calc(0.5rem + 0.3em) 0.7rem;
    background: rgba(169, 246, 219, 0.10);
    font-size: 0.75rem;
    line-height: 1.5;
    color: #ffffff;
}

/* Neun Laufzeiten (E2, Reiter 2). Feste Laufzeitspalte, damit die Zinswerte eine
   gemeinsame Kante bekommen; tabular-nums, damit die Kommastellen untereinander
   stehen — dasselbe Mittel wie in .zk-zeile-werte. NUR Zinssaetze: keine Rate,
   keine Gesamtkosten, keine Hochrechnung (E35). */
.zk-panel-overlay .zk-panel .zk-zinsmatrix { display: block; }
/* Das linke Polster tragen ALLE Zeilen, nicht nur die markierte: es ist der Platz
   fuer den Balken der gewaehlten Laufzeit (unten). Laege es allein an ihr, ruecke
   genau eine Zeile gegen alle anderen ein — die Zinswerte verloeren ihre
   gemeinsame Kante, und das ist in einer Matrix aus neun Laufzeiten der
   eigentliche Lesehelfer. */
.zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile {
    display: flex;
    flex-wrap: wrap;
    gap: 0.1rem 0.6rem;
    padding: 0.35rem 0 0.35rem 0.55rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile:last-child { border-bottom: 0; }
/* Die Zeile der GEWAEHLTEN Laufzeit. Der Core markiert sie mit aria-current und
   hat dafuer bewusst keine Klasse erfunden; sie kommt genau einmal je Template vor.
   ACHTUNG fuer den Core: [aria-current] trifft das Attribut UNABHAENGIG von seinem
   Wert. Ein aria-current="false" an den uebrigen acht Zeilen liesse alle neun
   markiert aussehen — das Attribut gehoert nur an die eine Zeile.

   E64 (Anwender-Entscheid 10.09.2026): DER BALKEN LINKS IST ENTFALLEN. Er war nach
   E62/E63 die letzte Stelle des Produkts mit gruenem Balken links, und die
   Bedeutungskollision haengt an der FARBE, nicht am Untergrund: gruener Balken links
   ist im Haus die Marke der positiven Kurzmeldung. Dass diese Zeile eine Auswahl in
   einer Datenmatrix markiert und keine Fundstelle, aendert daran nichts.

DREI nicht-farbliche Merkmale bleiben — und der Klartext allein traegt schon:
     1. Klartext "(gewaehlte Laufzeit)" im Markup des Cores, an gar keiner CSS-Regel
     2. fetter Zinswert (font-weight 700 gegen 400)
     3. abgerundete Ecke (border-radius 3.2px gegen 0px der acht anderen)
   Die GRUNDFLAECHE zaehlt hier NICHT mit: eine Fuellflaeche ist ein Helligkeits- und
   Farbunterschied, also genau das, wogegen P§8 sich richtet — sie ist der farbliche
   TRAEGER der Markierung, nicht ihr Formmerkmal. Der Hauspraezedenzfall E49 zaehlt
   entsprechend "verstaerkte Rautenkontur" und "verstaerkte Endkappe", also Kontur und
   Form, nicht Fuellung. (Richtiggestellt nach Review-Befund B1 des dritten Satzes;
   die erste Fassung zaehlte die Flaeche mit und uebersah den border-radius.)

   DIE FLAECHE BLEIBT MINT, anders als bei den beiden Uebersichts-Feldern in E62/E63.
   ZWEI gemessene Gruende, beide am DIESEM Element erhoben (nicht am Nachbarn — die
   erste Fassung uebernahm eine Kennzahl von .zk-repr-hinweis, das Mint 0.10 statt
   0.12 traegt; Review-Befund B2):
     a) Sie traegt hier. Mint 0.12 auf dem Panelgrund (Stapel rgba(9,87,143,0.92)
        ueber rgb(0,112,192) = rgb(8,3, 89, 146,9)) ergibt 43,2 % relativen
        Luminanzsprung — gegen 28,2 % derselben Deckkraft auf dem hellen Seitengrund.
     b) Und sie schadet hier nicht: der weisse Text misst darauf 5,73:1. Auf dem
        Seitengrund waren es 4,39:1, also UNTER AA — genau deshalb musste die Flaeche
        dort weichen und darf hier bleiben. DAS ist das eigentliche Unterscheidungs-
        merkmal zwischen E62/E63 und diesem Satz, nicht die Sichtbarkeit allein.
   Der Untergrund entscheidet, nicht die Farbe.

   ⚠ RELATIVE SPRUENGE SIND NUR INNERHALB EINER PALETTE VERGLEICHBAR. Dieselbe Zeile
   misst in der HELLEN Palette nur 12,6 % — nach der E62-Skala (17,9 % = "zu wenig")
   saehe das nach einem Mangel aus. Es ist keiner: der ABSOLUTE Abstand betraegt dort
   0,1192 und damit mehr als das Doppelte der 0,0554 der neuen dunklen
   Uebersichtsflaeche. Die Prozentzahl faellt nur klein aus, weil auf hellem Grund
   durch ein grosses L geteilt wird. Wer sie ueber beide Paletten hinweg vergleicht,
   erzeugt einen Scheinbefund.

   DAS LINKE POLSTER ALLER ZEILEN BLEIBT (0.55rem, Regel darueber). Es war der Platz
   fuer den Balken, aber es traegt einen zweiten Zweck: laege es allein an der
   markierten Zeile, ruecke genau eine Zeile gegen die acht anderen ein und die
   Zinswerte verloeren ihre gemeinsame Kante. Es zu entfernen waere eine
   Layout-Aenderung ohne Auftrag. */
.zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile[aria-current] {
    background: rgba(169, 246, 219, 0.12);
    border-radius: 0.2rem;
}
.zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile[aria-current] .zk-zinsmatrix-lz { color: #ffffff; }
.zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile[aria-current] .zk-zinsmatrix-wert { font-weight: 700; }
.zk-panel-overlay .zk-panel .zk-zinsmatrix-lz {
    flex: 0 0 7rem;
    color: #C3D3E2;
    font-size: 0.78rem;
    line-height: 1.45;
}
.zk-panel-overlay .zk-panel .zk-zinsmatrix-wert {
    flex: 1 1 8rem;
    min-width: 0;
    color: #ffffff;
    font-size: 0.82rem;
    line-height: 1.45;
    font-variant-numeric: tabular-nums;
}

/* Betrags-/Staffelzusatz INNERHALB eines Matrix- oder Sollzins-Wertes. Er loest den
   doppelten Doppelpunkt gestaffelter Werte auf und muss sich vom Zinswert absetzen.
   Vorbild ist .staffel-zusatz der Listenansicht (Listen-Core Z. 637-646): eigene
   Zeile, 0,7rem, Normalschnitt, kleiner Vorlauf ab dem zweiten Zusatz.

   EINE BENANNTE ABWEICHUNG, und zwar dieselbe wie an drei anderen Stellen dieser
   Datei: die Liste faerbt den Zusatz mit --text-muted. Das ist in der dunklen
   Palette rgba(255,255,255,0.5) und ergibt auf dem gemessenen Panelgrund
   rgb(8,89,147) den Mischwert rgb(132,172,201) = 3,05:1 — unter AA. Gedaempft wird
   hier deshalb ueber GROESSE UND SCHNITT, die Farbe bleibt auf der belegten
   Sekundaerstufe #C3D3E2 (4,80:1). Der Kopf dieser Datei haelt dasselbe Prinzip
   schon fuer Fussnote, Pflichtblock und die Bedienelemente fest: eine bekannte
   AA-Unterschreitung wird nicht in neues Markup kopiert. */
.zk-panel-overlay .zk-panel .zk-staffel-zusatz {
    display: block;
    margin-bottom: 0.1em;
    color: #C3D3E2;                 /* 4,80:1 */
    font-size: 0.7rem;
    font-weight: 400;
    line-height: 1.4;
}
.zk-panel-overlay .zk-panel .zk-staffel-zusatz:not(:first-child) { margin-top: 0.35em; }
/* In der markierten Zeile bleibt der Zusatz Beiwerk: der fette Schnitt des
   Zinswertes darf nicht auf ihn durchschlagen. */
.zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile[aria-current] .zk-staffel-zusatz { font-weight: 400; }

/* --- Panel-Fuss ----------------------------------------------------------
   REIHENFOLGE SEIT E56: Zusatz -> Sprung -> CTA. Der CTA steht damit als letztes
   Element unten rechts, wie in Festgeld und Brokerage. Der Fuss ist selbst eine
   Spalte mit align-items: flex-start, damit Zusatz und Sprung inhaltsbreit links
   stehen und allein der CTA per align-self ausschert.

   margin-top: auto STATT 0.9rem — das ist der Anker der Kette aus vier Gliedern
   (siehe .zk-panel-body). Im Scroll-Fall loest auto zu 0 auf; den Mindestabstand
   zum Inhalt darueber traegt dann padding-top plus der margin-bottom des letzten
   Inhaltsblocks (.zk-feldliste, 0.6rem).

   FUSSFREIRAUM SEIT E60 (A2 vom 10.09.2026): padding-top ist 0.75rem PLUS 1.5em.
   Der zusaetzliche Freiraum sitzt damit ZWISCHEN der Trennlinie und dem ersten
   Fusskind (.zk-detail-zusatz, bei fehlendem Zusatz der CTA) — der Anwender hat
   diese Lage gegen die Alternative "vor der Linie" entschieden: die Linie bleibt
   dicht am Flaecheninhalt, der Fussblock bekommt Luft nach innen. Waere der
   Freiraum vor der Linie gesetzt worden (padding-bottom am .zk-reiter-block),
   ruecke die Linie mit ab und die Zaesur saesse an der falschen Stelle.

   DIE EINHEITEN SIND ABSICHTLICH GEMISCHT: 0.75rem ist der Bestandswert und
   haengt an der Wurzel, die 1.5em sind der Auftragswert und haengen am
   Schriftgrad des Fusses (er erbt 0.9rem von .zk-panel, also 14,4 px bei 16 px
   Wurzel -> 21,6 px Zuwachs, Summe 33,6 px). calc() statt eines ausgerechneten
   Einzelwerts, damit beide Bezuege sichtbar bleiben und ein spaeterer
   Schriftgrad-Wechsel den Freiraum mitzieht.

   IM SHEET (<= 48em) GILT DIESELBE REGEL: der 48em-Block setzt am Fuss KEIN
   eigenes padding-top (geprueft 10.09.2026), und die Panelschrift bleibt dort
   ebenfalls 0.9rem — der Freiraum wirkt in beiden Modi gleich. Wer im Sheet
   spaeter ein eigenes padding-top ergaenzt, muss die 1.5em mitnehmen. */
.zk-panel-overlay .zk-panel .zk-detail-fuss {
    margin-top: auto;
    padding-top: calc(0.75rem + 1.5em);
    border-top: 1px solid rgba(255, 255, 255, 0.18);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}
/* CTA in der Optik von .zg-karte .zg-dk-cta (Festgeld DE, E56), aber mit
   LITERALEN statt var(): das Vorbild ist Nachfahre von .vergleich-dashboard und
   loest --accent/--primary-darker/--radius-sm/--space-xs/--transition-fast dort
   auf. Dieses Panel liegt AUSSERHALB der .vergleich-dashboard (Recon A.4) — jede
   var() fiele hier auf ihren Fallback zurueck oder ins Leere. Dasselbe Muster
   faehrt das Tagesgeld-Panel, und derselbe Grund traegt den ganzen Hell-Block in
   Abschnitt 21.
   Drei Klassen im Selektor auch gegen die unscoped a-Regeln aus style.css (E32).
   Kontrast gerechnet: #004578 auf #A9F6DB = 7,96:1, Chip #ffffff auf #004578 =
   9,90:1. */
.zk-panel-overlay .zk-panel .zk-detail-cta {
    display: inline-flex;
    align-items: center;
    align-self: flex-end;
    gap: 0.25rem;
    margin-top: 0.9rem;
    padding: 0.8em 1.3em;
    background: #A9F6DB;
    color: #004578;
    text-decoration: none;
    font-weight: 600;
    font-size: 1rem;
    line-height: 1.35;
    border-radius: 0.5rem;
    transition: background 150ms ease;
}
.zk-panel-overlay .zk-panel .zk-detail-cta:hover,
.zk-panel-overlay .zk-panel .zk-detail-cta:focus {
    background: #DFFDF2;
    color: #004578;
    text-decoration: none;
}
.zk-panel-overlay .zk-panel .zk-detail-cta:focus-visible {
    outline: 0.125em solid #ffffff;
    outline-offset: 0.125em;
}
/* Das globale a::after-Icon (Fontello-Glyph fuer externe Links aus style.css)
   unterdruecken — der Pfeil-Chip tritt an seine Stelle. !important ist hier das
   Haus-Muster (Liste .anbieter-link::after, Festgeld .zg-dk-cta::after,
   Tagesgeld): content laesst sich ueber Spezifitaet nicht zuverlaessig
   zuruecknehmen, weil die Bestandsregel selbst schon !important traegt. Es ist
   die EINZIGE !important-Stelle dieses Abschnitts. */
.zk-panel-overlay .zk-panel .zk-detail-cta::after,
.zk-panel-overlay .zk-panel .zk-detail-cta:hover::after { content: none !important; display: none !important; }
/* Pfeil-Chip. Die unscoped .link-arrow-Regel der Liste greift auf den
   Diagrammseiten nicht (am Vorbild gemessen: Probe-Chip ungestylt), deshalb voll
   definiert. Gegen das Vorbild in em/rem statt px umgerechnet (E32): 18px ->
   1.5em bei 0.75rem Chip-Schrift, 12px -> 0.75rem, 6px -> 0.5em, -3px ->
   -0.1875em, 1px -> 0.0625em. */
.zk-panel-overlay .zk-panel .zk-detail-cta .link-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5em;
    height: 1.5em;
    background: #004578;
    color: #ffffff;
    border-radius: 50%;
    font-size: 0.75rem;
    line-height: 1;
    margin-left: 0.5em;
    position: relative;
    top: -0.1875em;
    padding-bottom: 0.0625em;
}
/* Der Fuss traegt seit E59 nur noch ZWEI Kinder: Zusatz und CTA. Der Sprunglink
   ist mit E59 aus dem Fuss in die Reiterflaechen gewandert (Markup im Core, Regel
   weiter unten) — die frueher hier stehende Reihenfolge "Zusatz -> Sprung -> CTA"
   ist damit "Zusatz -> CTA". Der Zusatz ist das erste Element und beginnt bei 0.
   Er behaelt display: inline-block — als Flex-Kind wird es ohnehin zu block
   blockifiziert, die Deklaration schadet nicht und traegt, falls der Fuss je ohne
   Flex-Kontext gerendert wird. Der Zusatz ist ein <p>; die Leak-Reset-Regel
   .zk-panel-overlay .zk-panel p (0,2,1) setzt margin: 0 und verliert gegen diesen
   Selektor (0,3,0) — genau die Falle des ?v=12-Satzes, hier bewusst geprueft. */
.zk-panel-overlay .zk-panel .zk-detail-zusatz {
    margin: 0;
    font-size: 0.75rem;
    line-height: 1.5;
    color: #C3D3E2;
}
/* Zweiter Weg zum Pflichtblock (E44 Punkt 2) — zusaetzlich zum Zeilen-Link, nicht
   an seiner Stelle. Weiss mit Unterstreichung wie a.zk-sprung: Mint, Blau und
   Violett sind in dieser Ansicht semantisch belegt.

   ORT SEIT E59: IN DEN FLAECHEN STATT IM FUSS. Der Link steht als letztes Kind in
   .zk-reiterflaeche[data-gruppe="zinssaetze"] (nach .zk-zinsmatrix) und in
   [data-gruppe="merkmale"] (nach .zk-feldliste), nicht mehr im .zk-detail-fuss.
   Grund: im Reiter "Zinsangebot" steht das vollstaendige Beispiel schon in der
   Flaeche, dort waere der Sprung ein Verweis auf bereits Gelesenes. Der Fuss lag
   ausserhalb der Flaechen und konnte nicht je Reiter unterscheiden — nur ein
   Ortswechsel im Markup loest das ohne Zustandsklasse aus der Engine.

   DIE REGEL SELBST BLEIBT UNVERAENDERT und musste es: margin-top 0.5rem traegt in
   beiden Flaechen (gemessen 10.09.2026, Abstand zur Matrix bzw. zur Feldliste),
   Farbe, Unterstreichung und Fokusring sind dieselben wie im Fuss. display:
   inline-block ist jetzt wirksam statt blockifiziert — die Flaeche ist ein
   Blockcontainer, kein Flex-Container: der Link wird inhaltsbreit, sein Fokusring
   umschliesst nur den Text statt der ganzen Zeilenbreite. Das ist die bessere
   Fassung, nicht bloss die unveraenderte. */
.zk-panel-overlay .zk-panel .zk-detail-sprung {
    display: inline-block;
    margin-top: 0.5rem;
    color: #ffffff;
    font-size: 0.78rem;
    line-height: 1.45;
    text-decoration: underline;
}
/* Untere Marge des Links IN DEN FLAECHEN (E59-Nachtrag, Smoke-Befund B1 vom 10.09.2026):
   Seit E59 ist der Link das letzte Kind der Flaechen "alle Zinssaetze" und "Merkmale". Im
   Scroll-Fall endet die Flaeche damit am Link, und der stand gemessen 0,34 px ueber der
   Trennlinie des Fusses -- vorher war das letzte Kind die .zk-feldliste mit ihrer unteren
   Marge 0.6rem (9,6 px). Diese Marge bekommt der Link jetzt selbst, damit der Abstand zur
   Linie derselbe bleibt wie vor E59. Die Marge wirkt, weil der Link inline-block ist
   (vertikale Margen eines inline-block zaehlen in der Zeilenbox mit, anders als bei
   inline). Im Anker-Fall (margin-top: auto am Fuss) ist sie ohne sichtbare Wirkung.
   Drei Klassen plus Flaeche (0,4,0): spezifischer als die Grundregel darueber, damit
   ein spaeterer Ort des Links ausserhalb einer Flaeche die Marge nicht mitnimmt. */
.zk-panel-overlay .zk-panel .zk-reiterflaeche .zk-detail-sprung { margin-bottom: 0.6rem; }
.zk-panel-overlay .zk-panel .zk-detail-sprung:hover,
.zk-panel-overlay .zk-panel .zk-detail-sprung:focus { text-decoration: none; }
.zk-panel-overlay .zk-panel .zk-detail-sprung:focus-visible {
    outline: 0.125rem solid #A9F6DB;
    outline-offset: 0.125rem;
}

/* Ersatzinhalt, wenn der Filter die Zeile des offenen Panels ausschliesst (E43).
   Er ersetzt den Body-Inhalt; Overlay, Fokus und Scroll-Lock bleiben unangetastet.
   #vergleich im Selektor aus demselben gemessenen Grund wie bei .zk-repr-hinweis:
   #vergleich p aus style.css traegt (1,0,1) und toetete hier padding und
   line-height. */
#vergleich .zk-panel-overlay .zk-panel .zk-panel-hinweis {
    margin: 1em 0;
    padding: calc(0.8rem + 0.3em) 0.9rem;
    background: rgba(169, 246, 219, 0.10);
    font-size: 0.85rem;
    line-height: 1.5;
    color: #ffffff;
}

/* --- Bottom-Sheet <= 48em (E3, an E53/E56 angepasst) --------------------- */
@media (max-width: 48em) {
    /* Die Overlay-Regel dieses Blocks ist mit E53 entfallen: align-items ist
       ohne Flex-Container wirkungslos, und padding: 0 steht seither schon in
       der Basisregel. Das Sheet dockt sich wie das Seitenpanel selbst an — hier
       an drei Kanten statt an einer. */
    .zk-panel-overlay .zk-panel {
        top: auto;
        right: 0;
        bottom: 0;
        left: 0;
        width: 100%;
        max-width: none;
        height: auto;               /* inhaltshoch, nicht viewporthoch */
        max-height: 85vh;           /* eigener Scroll, siehe .zk-panel-body */
        padding: 1.5em 1.1em 1.25em;
        border-left: none;
        border-top: 0.0625em solid rgba(76, 181, 160, 0.45);
        border-radius: 0.9rem 0.9rem 0 0;
        box-shadow: 0 -0.5em 2em rgba(0, 26, 48, 0.4);   /* Schatten nach oben */
    }
    /* Hier kehrt das Rechtspolster des Titels zurueck: die Kopfzone des
       Seitenpanels (4.65em) gibt es im Sheet nicht, der Knopf sitzt neben dem
       Titel. 3.25rem = 52 px decken Knopf (2.75rem = 44 px) plus Versatz
       (0.55em = 11 px) minus dem Panelpolster (1.1em bei 0.9rem = 15,84 px). */
    .zk-panel-overlay .zk-panel-titel { padding-right: 3.25rem; }
    /* Knopfmass des Sheets nach .zg-sheet-close. Die Core-Regel setzt im eigenen
       Haltepunkt ebenfalls 2.75rem, aber nur mit 0,1,0 — sie verlaere gegen die
       0,3,0 der Basisregel oben. Deshalb steht das Mass hier noch einmal. */
    .zk-panel-overlay .zk-panel .zk-panel-close {
        width: 2.75rem;
        height: 2.75rem;
        top: 0.45em;
        right: 0.55em;
    }
    /* Die Einblendung wechselt die Richtung mit: ein Bottom-Sheet, das von der
       Seite einfaehrt, widerspricht seiner eigenen Form. */
    .zk-panel-overlay[data-offen] .zk-panel { animation-name: zk-panel-ein-sheet; }
    /* Name und Wert untereinander — 10rem Namensspalte plus Wert passen bei
       375 px Viewport nicht nebeneinander. */
    .zk-panel-overlay .zk-panel .zk-feld-name,
    .zk-panel-overlay .zk-panel .zk-zinsmatrix-lz { flex: 1 1 100%; }
    .zk-panel-overlay .zk-panel .zk-reiterleiste { gap: 0.15rem; }
    .zk-panel-overlay .zk-panel .zk-reiter { padding: 0.4rem 0.55rem; font-size: 0.78rem; }
}
@media (prefers-reduced-motion: reduce) and (max-width: 48em) {
    /* Das Pendant muss den Haltepunkt mitnehmen — sonst bliebe unter 48em die
       Sheet-Animation aktiv, obwohl die Einstellung sie abbestellt hat. */
    .zk-panel-overlay[data-offen] .zk-panel { animation: none; opacity: 1; transform: none; }
}

/* ==========================================================================
   20b) ZEILEN-RESET UND SPRUNGLINK (Phase 4, E39a, Recon F7)

   Neue Zeilenstruktur seit E39a:

     div.zk-zeile.zk-raster#zk-zeile-<IDS>      ← Container, AEUSSERES Raster
     ├── button.zk-zeile-flaeche                ← Ausloeser, INNERES Raster
     │   ├── .zk-zeile-label
     │   └── .zk-spur
     └── a.zk-sprung                            ← GESCHWISTER, nicht Nachfahre

   Der Button bringt text-align: center, eigene Font-Vererbung, border, background,
   in manchen Engines overflow: hidden und ein eigenes Fokus-Styling mit. Ohne
   Reset zerfaellt das Raster. DER RESET STEHT IM CSS, nicht im JS: er muss vor dem
   ersten FLIP-Lauf greifen, und ein per JS gesetzter Stil kaeme einen Frame zu
   spaet — sichtbar als Sprung genau in dem Moment, in dem die Zeilen sich bewegen.

   ZWEI RASTER, EINE ZEILE: die Flaeche spannt sich im aeusseren Raster ueber beide
   Spalten (grid-column: 1 / -1) und traegt innen dieselben zwei Spalten
   (Abschnitt 3). Der Sprunglink sitzt darunter in Spalte 1, also unter dem Label —
   dort, wo er vor Phase 4 innerhalb von p.zk-zeile-repr stand.

   position: relative bekommt .zk-zeile bewusst NICHT. Nichts wird relativ zur
   Zeile absolut positioniert; was positioniert werden muss, haengt an .zk-spur,
   und die BEHAELT ihr position: relative (Abschnitt 7). Die sticky Achse traegt
   z-index: 4 und soll ueber den Zeilen bleiben — eine Aenderung an deren
   Positionierung ohne Not ist genau die Sorte Eingriff, die die Leiter-Geometrie
   kostet.
   ========================================================================== */
.zinskorridore-dashboard .zk-leiter .zk-zeile-flaeche {
    grid-column: 1 / -1;
    width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    text-transform: none;
    letter-spacing: inherit;
    overflow: visible;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    /* E39a Auflage: die Textauswahl in der Zeile darf der Umbau nicht kosten.
       Browser setzen auf <button> user-select: none. */
    -webkit-user-select: text;
    user-select: text;
}
/* Ruhige Flaechenmarkierung beim Ueberfahren. Kein Rahmen und kein Polster: beides
   aenderte die Zeilenhoehe und verschoebe waehrend eines FLIP-Laufs die gemessenen
   Positionen. */
.zinskorridore-dashboard .zk-leiter .zk-zeile-flaeche:hover {
    background: rgba(255, 255, 255, 0.05);
    border-radius: 0.25rem;
}
.zinskorridore-dashboard .zk-leiter .zk-zeile-flaeche:focus-visible {
    outline: 0.125rem solid var(--accent, #A9F6DB);
    outline-offset: 0.125rem;
    border-radius: 0.25rem;
}

/* Der Sprunglink im Raster. EIGENES Fokusbild (gepunktet plus Mint-Chip) gegen den
   durchgezogenen Ring der Flaeche — E39a verlangt ausdruecklich, dass die zweite
   Station der Tab-Reihenfolge nicht als Wiederholung der ersten gelesen wird.
   Drei Klassen im Selektor gegen die unscoped a-Regeln aus style.css. */
.zinskorridore-dashboard .zk-buehne .zk-sprung {
    grid-column: 1;
    justify-self: start;
    margin-top: 0.1rem;
}
.zinskorridore-dashboard .zk-buehne .zk-sprung:focus-visible {
    outline: 0.125rem dotted var(--accent, #A9F6DB);
    outline-offset: 0.2rem;
    background: rgba(169, 246, 219, 0.18);
    border-radius: 0.2rem;
    text-decoration: none;
}

/* ==========================================================================
   20c) HOVER/FOKUS-KOPPLUNG ZEILE <-> BAND <-> RAUTE (Bauplan S7)

   Band, Punkt und Raute sind seit E39a KINDER der Ausloeser-Flaeche. Die Kopplung
   braucht deshalb keine Zeile JavaScript. :focus-visible statt :focus, damit ein
   Mausklick auf die Zeile keinen Ring hinterlaesst.

   Hervorgehoben wird ausschliesslich mit box-shadow. Kein transform (die Raute
   traegt bereits rotate(45deg) und verloere ihre Form), keine Rahmenbreite, kein
   Polster — beides aenderte die Geometrie waehrend eines FLIP-Laufs. Kein
   !important auf FLIP-Eigenschaften.

   Der Pflichtblock-Eintrag unterhalb der Leiter ist KEIN Kind der Flaeche und
   deshalb per CSS nicht erreichbar — ihn markiert die Engine mit
   .zk-beispiel-hervor auf #zk-beispiel-<IDS>. Das ist der einzige Klassenname,
   den CSS und Engine sich teilen.
   ========================================================================== */
.zinskorridore-dashboard .zk-zeile-flaeche:hover .zk-band,
.zinskorridore-dashboard .zk-zeile-flaeche:focus-visible .zk-band,
.zinskorridore-dashboard .zk-zeile-flaeche:hover .zk-punkt,
.zinskorridore-dashboard .zk-zeile-flaeche:focus-visible .zk-punkt {
    box-shadow: 0 0 0 0.125rem var(--zk-raute-fuell);
}
.zinskorridore-dashboard .zk-zeile-flaeche:hover .zk-raute,
.zinskorridore-dashboard .zk-zeile-flaeche:focus-visible .zk-raute {
    box-shadow: 0 0 0 0.16rem var(--zk-grund), 0 0 0 0.3rem var(--zk-raute-fuell);
}
/* Die Achsenrand-Raute traegt ihre offene Doppelkontur SELBST als box-shadow
   (Abschnitt 8). Ohne diese eigene Regel loeschte die Kopplung sie beim
   Ueberfahren aus und naehme der Zeile genau die Information, die sie
   kennzeichnet. Gleiche Spezifizitaet wie oben, spaeter in der Datei — gewinnt. */
.zinskorridore-dashboard .zk-zeile-flaeche:hover .zk-raute-achsenrand,
.zinskorridore-dashboard .zk-zeile-flaeche:focus-visible .zk-raute-achsenrand {
    box-shadow:
        0 0 0 0.16rem var(--zk-grund),
        0 0 0 0.28rem var(--zk-konflikt),
        0 0 0 0.44rem var(--zk-raute-fuell);
}

/* Gegenstueck im Pflichtblock — die Sprungziel-Marke des angesprungenen Eintrags.

   E63 (Anwender-Entscheid 10.09.2026): Der MINT-BALKEN LINKS IST ENTFALLEN, aus
   demselben Grund wie an den vier Hinweisfeldern (E62) — der gruene Balken ist im
   Haus die Marke der positiven Kurzmeldung, und ein angesprungener Pflichtblock-
   Eintrag ist keine gute Nachricht, sondern eine Fundstelle. Sie markiert zwar eine
   ZEILE und kein Hinweisfeld, aber die Bedeutungskollision trifft sie genauso.

   Die Flaeche wechselt dabei auf denselben dunklen Ton wie die beiden
   Uebersichts-Felder, und aus demselben gemessenen Grund: dieser Block steht auf dem
   SEITEN-Grund #0070C0, nicht auf der Buehne. Mint 0.12 traegt dort einen relativen
   Luminanzsprung von 26,8 % — sichtbarer als die 17,9 % der Fussnote, aber ohne den
   Balken zu wenig fuer eine Marke — und drueckt den weissen Text auf 4,28:1, also
   UNTER die AA-Schwelle 4,5:1. rgba(4,26,45,0.25) misst 37,1 % und 7,15:1.

   KEIN Polster hinzugefuegt, obwohl die Flaeche jetzt buendig am Text liegt: die
   Pflichtliste wird von der Engine parallel zur Leiter per FLIP umsortiert
   (Abschnitt 16), und eine Layout-Aenderung waehrend des Laufs verschoebe die
   gemessenen Positionen. Aus demselben Grund war der Balken nie ein border-left,
   sondern ein INSET-box-shadow. Wer hier Polster will, braucht einen eigenen
   Auftrag und eine FLIP-Messung dazu. */
.zinskorridore-dashboard .zk-pflichtblock .zk-beispiel-hervor {
    background: rgba(4, 26, 45, 0.25);
    border-radius: 0.2rem;
}

/* ==========================================================================
   21) HOCHKONTRAST-HELL DES PANELS UND DER KOPPLUNG (Phase 4, E30)

   Vollstaendige zweite Palette, kein Weiss-Tausch der Normalpalette. Die
   Panel-Huelle liegt genau deshalb innerhalb von #vergleich (Recon A.4) — die
   .kontrast-hell-Kaskade greift dort, obwohl die Huelle ausserhalb der
   .vergleich-dashboard steht.

   DIESER ABSCHNITT IST PFLICHT UND NICHT KOSMETIK: --accent ist in
   vergleich.min.css ausschliesslich auf .vergleich-dashboard definiert
   (#A9F6DB, unter kontrast-hell #00528D). Das Panel liegt ausserhalb; dort faellt
   var(--accent) in BEIDEN Paletten auf den Mint-Fallback zurueck. Mint auf weissem
   Panelgrund traegt 1,24:1 — ein unsichtbarer Fokusring. Deshalb stehen alle
   Panel-Farben als Literale und werden hier vollstaendig getauscht.

   Alle Overrides ueber Spezifizitaet (ID plus Klassen), nie ueber !important,
   keine Geometrie-Aenderung.
   ========================================================================== */
/* Panel-Huelle (Werte des Vorbilds, E53). Der Weichzeichner wird hier
   ausdruecklich abgeschaltet: auf mattem #F7F9FC hat er nichts zu zeichnen und
   kostet nur eine Compositing-Ebene. Die Kante steht seit E53 nur noch links —
   border-color traefe zwar weiterhin alle vier Seiten, aber drei davon sind
   none, und border-left-color sagt, was gemeint ist. Kontrast #22303c auf
   #F7F9FC = 12,79:1.

   SCHATTEN-RICHTUNG NACHGEZOGEN (gemessen 10.09.2026, Vorabmessung dieser
   Politur): Der helle Satz stand auf 0 0.5em 2.5em / 0 0.125em 0.5em — nach
   UNTEN. Das passte zum zentrierten Fenster, das hier bis zum 10.09.2026 stand.
   An einem rechts angedockten Panel faellt ein Schatten nach unten hinter die
   Viewport-Kante und trennt gar nichts mehr; dieselbe Lage im Bottom-Sheet, wo
   er unter den Bildschirmrand faellt. Die STAERKE des hellen Satzes bleibt
   unveraendert (zwei Lagen, neutrales Schwarz statt des dunkelblauen
   Panelschattens — auf hellem Grund traegt weniger), nur die Achse dreht auf
   dieselbe Richtung wie in der dunklen Palette. Das Vorbild fasst seinen
   Schatten im Hell-Block gar nicht erst an; hier steht er nur deshalb, weil die
   helle Palette eine eigene Staerke fuehrt. */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel {
    background: #F7F9FC;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-left-color: #00528D;
    box-shadow:
        -0.5em 0 2.5em rgba(0, 0, 0, 0.25),
        -0.125em 0 0.5em rgba(0, 0, 0, 0.15);
    color: #22303c;                 /* 12,79:1 */
}
/* Heller Scrim: derselbe Wert wie bei den modalen Haus-Schwestern, nur mit
   geringerer Deckkraft — auf hellem Seitengrund traegt schon weniger Verdunklung
   die Abtrennung. */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel-backdrop { background: rgba(0, 26, 48, 0.35); }
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel-titel { color: #0b2035; }
/* Schliessknopf (E56), Werte des Vorbilds. Spezifitaet 1,4,0 bzw. 1,5,0 — sie
   muss ueber der Core-Hellregel #vergleich.kontrast-hell .panel-close-btn (1,2,0)
   und ihrem :hover/:focus-Zweig (1,3,0) liegen, sonst schluege der Bestandsgrund
   durch. :focus steht wie in der dunklen Palette mit im Hover-Zweig.
   Kontrast #003A66 auf dem gemischten Knopfgrund = 9,07:1. */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-panel-close {
    background: rgba(0, 82, 141, 0.12);
    color: #003A66;
}
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-panel-close:hover,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-panel-close:focus {
    background: rgba(0, 82, 141, 0.22);
    color: #003A66;
}
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-panel-close:focus-visible { outline-color: #00528D; }

#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-reiterleiste { border-bottom-color: rgba(0, 82, 141, 0.30); }
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-reiter { color: #3C4F5E; }   /* 8,50:1 */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-reiter:hover { color: #00528D; }
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-reiter.active,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-reiter[aria-selected="true"] {
    color: #00528D;                 /* 8,10:1 */
    background: rgba(0, 82, 141, 0.08);
    border-bottom-color: #00528D;
}
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-reiter:focus-visible { outline-color: #0070C0; }  /* 5,15:1 */

#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-feld,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile { border-bottom-color: rgba(0, 82, 141, 0.18); }
/* .zk-beispiel-titel (E58) steht bewusst in DIESER Gruppe und nicht bei den
   Textfarben darunter: er ist eine Beschriftung in Feldnamen-Optik, also derselbe
   Ton wie .zk-feld-name — dunkel #C3D3E2, hell #3C4F5E. Der Beispieltext unter ihm
   traegt weiter die volle Textfarbe (#0b2035), die Abstufung Beschriftung/Text
   bleibt in beiden Paletten erhalten. */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-beispiel-titel,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-feld-name,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-zinsmatrix-lz,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-staffel-zusatz,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-zusatz { color: #3C4F5E; }
/* Gewaehlte Laufzeit. Balken und Flaeche wechseln auf den Blauton der hellen
   Palette; der fette Zinswert und der Klartext im Markup tragen unveraendert. */
/* Hell nur der Balken weg (E64); die Flaeche bleibt. */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile[aria-current] {
    background: rgba(0, 82, 141, 0.08);
}
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-zinsmatrix-zeile[aria-current] .zk-zinsmatrix-lz { color: #00528D; }
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-feld-wert,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-zinsmatrix-wert,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-beispieltext,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-beispieltext .beispiel-pa { color: #0b2035; }
/* Zeichengleich zu Liste (Z. 1281), Tabelle (Z. 1588) und zum Pflichtblock in
   Abschnitt 12 — eine vierte Optik derselben Pflichtangabe waere Cross-View-Drift. */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-beispieltext .beispiel-effzins { color: #00528D; }

#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-repr-hinweis,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-panel-hinweis {
    background: rgba(0, 82, 141, 0.08);
    color: #0b2035;
}
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-fuss { border-top-color: rgba(0, 82, 141, 0.22); }
/* CTA-Hell = Listen-Kontrast (E56, wie Festgeld DE): #0070C0 auf weiss = 5,15:1,
   Hover eine Stufe dunkler. Die Richtung ist damit gegen frueher GEDREHT — bis
   zum 10.09.2026 stand hier #00528D mit #0070C0 als Hover. Der Chip kehrt die
   Flaechen um: heller Grund, blaue Glyphe (#F7F9FC auf #00528D = 7,68:1). */
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-cta {
    background: #0070C0;
    color: #ffffff;                 /* 5,15:1 */
}
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-cta:hover,
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-cta:focus { background: #00528D; color: #ffffff; }
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-cta:focus-visible { outline-color: #003A66; }
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-cta .link-arrow {
    background: #F7F9FC;
    color: #00528D;
}
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-sprung { color: #00528D; }
#vergleich.kontrast-hell .zk-panel-overlay .zk-panel .zk-detail-sprung:focus-visible { outline-color: #0070C0; }
/* Hell-Pendant der SHEET-Kante und des Sheet-Schattens. Beides braucht den
   Haltepunkt, weil <= 48em die Kante von links nach oben wechselt und der
   Schatten mit ihr; ohne diese Regel bliebe im hellen Sheet die dunkle
   Mint-Kante stehen und der Schatten zeigte weiter nach links, wo im Sheet
   keine freie Kante mehr ist. Die Regel traegt 1,2,0 und schlaegt damit die
   0,2,0 des Sheet-Blocks in Abschnitt 20. */
@media (max-width: 48em) {
    #vergleich.kontrast-hell .zk-panel-overlay .zk-panel {
        border-top-color: #00528D;
        box-shadow:
            0 -0.5em 2.5em rgba(0, 0, 0, 0.25),
            0 -0.125em 0.5em rgba(0, 0, 0, 0.15);
    }
}

/* Zeile und Sprunglink. Denselben Wechsel auf #0070C0 macht der Bestand bereits
   fuer .anpassen-filter-btn und Phase 3 fuer die Sortierleiste: Mint auf weissem
   Grund traegt als Fokusmarkierung nicht. Die Flaechenmarkierung braucht einen
   dunklen Ton — rgba(255,255,255,0.05) waere auf weisser Buehne unsichtbar. */
#vergleich.kontrast-hell .zinskorridore-dashboard .zk-leiter .zk-zeile-flaeche:hover {
    background: rgba(0, 82, 141, 0.06);
}
#vergleich.kontrast-hell .zinskorridore-dashboard .zk-leiter .zk-zeile-flaeche:focus-visible { outline-color: #0070C0; }
#vergleich.kontrast-hell .zinskorridore-dashboard .zk-buehne .zk-sprung:focus-visible {
    outline-color: #0070C0;
    background: rgba(0, 112, 192, 0.12);
}
/* Der Kopplungs-Schein an Band, Punkt und Raute zieht seine Farben aus den Custom
   Properties (--zk-raute-fuell, --zk-grund, --zk-konflikt) und schaltet mit der
   Palette von allein mit — dort ist NICHTS nachzuziehen. Der Pflichtblock dagegen
   steht auf dem SEITEN-Grund, nicht auf der Buehne, und seine Marke traegt keine
   Custom Property: */
/* Hell nur der Balken weg (E63). Die Flaeche bleibt: auf weissem Grund traegt
   rgba(0,112,192,0.10) einen relativen Sprung von 13,4 %, und der Text ist dort
   dunkel — beides unproblematisch, anders als in der dunklen Palette. */
#vergleich.kontrast-hell .zinskorridore-dashboard .zk-pflichtblock .zk-beispiel-hervor {
    background: rgba(0, 112, 192, 0.10);
}

/* ==========================================================================
   22) E44 PUNKT 1 — VRT-BEFUND N3 IM "WEITERE FILTER"-PANEL

   Gemessen im VRT der Phase 3: die Beschriftungen des Filter-Panels erreichen in
   der DUNKLEN Palette 4,48:1 (rgba(255,255,255,0.7) auf gemessenem rgb(8,89,147))
   und verfehlen AA um 0,02. Ursache ist die Deckkraft 0,7, die die Regeln aus dem
   Inline-Block des Cores ueber --text-secondary beziehen.

   Angehoben auf rgba(255,255,255,0.82) = 5,51:1, gerechnet gegen denselben
   gemessenen Grund. Bewusst keine volle Weissstufe: die Abstufung zwischen
   Gruppentitel und Feldwert ist die einzige Hierarchie, die dieses Panel hat.

   WARUM DIE REGEL HIER STEHT und nicht im Inline-Block des Cores: dieser
   Bauabschnitt aendert genau eine Datei. Sie gewinnt ueber Spezifizitaet
   (1,3,0 gegen die 0,1,0 der Core-Regeln), nicht ueber !important.

   :not(.kontrast-hell) ist NICHT Zierde. Die hellen Pendants liegen bereits bei
   8,10:1 bzw. 12,63:1, und sie kommen teils gar nicht aus dem Core, sondern aus
   --text-secondary, das vergleich.min.css unter kontrast-hell selbst auf
   rgba(0,0,0,0.88) tauscht. Ein Weisston ohne diese Klammer machte die helle
   Palette unlesbar — aus einer 0,02-Unterschreitung wuerde ein echter Defekt.

   Die :hover-Zeile muss mit: die Bestandsregel .sidebar-filter-checkbox:hover
   traegt 0,2,0 und wuerde von der Basisregel oben (1,3,0) sonst geschlagen — der
   Hover-Aufhellung ginge damit ihre Wirkung verloren.

   DIE LISTENANSICHT BLEIBT UNVERAENDERT. Die entstehende Divergenz ist bewusst
   (E44 Punkt 1) und gehoert in den Befund des cross-view-konsistenz-pruefer.
   ========================================================================== */
#vergleich:not(.kontrast-hell) .anpassen-panel .sidebar-filter-title,
#vergleich:not(.kontrast-hell) .anpassen-panel .sidebar-filter-checkbox,
#vergleich:not(.kontrast-hell) .anpassen-panel .eingrenzungsfilter-hint {
    color: rgba(255, 255, 255, 0.82);
}
#vergleich:not(.kontrast-hell) .anpassen-panel .sidebar-filter-checkbox:hover {
    color: #ffffff;
}
