
    /* 50.01em statt 50em (Audit A-7.2 / Phase K6, Rollout Tagesgeld CT-0148 2026-08-26):
       zusammen mit dem `max-width: 50em`-Block darunter traf exakt 800px BEIDE Bloecke.
       Der Offset sitzt bewusst auf der min-width-Seite, damit 800px zur schmalen
       Variante gehoert; folgt dem Bestands-Vorbild `min-width: 72.01em`. `.01em` statt
       `.0625em`, weil letzteres exakt 801px waere und eine volle Pixel-Breite
       unversorgt liesse. Der `max-width: 50em`-Block bleibt unveraendert. */
    @media (min-width: 50.01em) {
        .filter-row-separator[style] .filter-column-separator { border-top: none; padding-top: 0; margin-top: 0; border-left: 1px solid var(--border); padding-left: var(--space-lg); margin-left: var(--space-md); }
    }
    @media (max-width: 50em) {
        .filter-row-separator[style] { grid-template-columns: 1fr !important; }
    }
    .filter-checkbox {
        display: flex; align-items: center; gap: 0.5em;
        padding: 0.375em 0; min-height: 2.25rem;
        cursor: pointer; font-size: 0.85rem;
        color: var(--text-secondary, #aab);
        transition: color 150ms ease; line-height: 1.35;
    }
    .filter-checkbox:hover { color: var(--text-primary, #fff); }
    .filter-checkbox input[type="checkbox"] {
        width: 1.25rem; height: 1.25rem; min-width: 1.25rem;
        accent-color: #00528d; cursor: pointer;
    }
    .filter-checkbox input[type="checkbox"]:checked + span {
        color: var(--text-primary, #fff); font-weight: 600;
    }
    @media (max-width: 48em) {
        /* Politur 2026-06-11d: EINZEILIGER Header auf Mobile. Der
           Treffer-Zaehler ("X Treffer · Anlagebetrag Y") ist ausgeblendet —
           Anwender-Entscheidung: Treffer-Anzahl steckt bereits im Pager
           ("von N"), der gewaehlte Anlagebetrag in den Einstellungen.
           display:none entfernt nur die Darstellung; die Trefferzahl
           bleibt fuer Crawler im separaten meta-Element daneben erhalten
           (K7 2026-08-13 - der sichtbare Zaehler traegt die Auszeichnung
           seitdem nicht mehr).
           Zeile: Pager links (kompakt — Skala-Track ausgeblendet, Platz
           reicht neben den Sort-Buttons nicht; Chevron-Paar bleibt) +
           `.sort-buttons` rechts (margin-left: auto). Site-CSS-Default
           (`flex-direction: column; align-items: stretch`) wird mit
           `row` + `flex-wrap: wrap` ueberschrieben — Spezifizitaet
           `.vergleich-dashboard.tabelle-dashboard .results-header`
           (0,3,0) schlaegt das Site-Default sauber. */
        .vergleich-dashboard.tabelle-dashboard .results-header {
            flex-direction: row;
            flex-wrap: wrap;
            align-items: center;
            row-gap: 0.4em;
        }
        .vergleich-dashboard.tabelle-dashboard .result-count {
            display: none;
        }
        .vergleich-dashboard.tabelle-dashboard .sort-buttons {
            align-self: center;
            margin-left: auto;
            /* 11h: 2.5%-Desktop-Randabstand auf Mobile opfern —
               jeder Pixel zaehlt fuer den Einzeiler. */
            margin-right: 0;
            /* Politur 2026-06-01b: das laengere Sonderzins-Sortier-Wording
               ("Jahresrendite bei beruecksichtigtem Sonderzins absteigend")
               sprengte bei 375px den Viewport (~46px Overflow), weil die Pille
               einzeilig blieb und .sort-buttons (global flex-shrink: 0) nicht
               nachgab. min-width:0 + flex-shrink:1 loesen die Sperre, der
               Button-Text bricht via white-space:normal um statt zu ueberlaufen
               — analog zum Listen-Verhalten (dort column+stretch). */
            min-width: 0;
            flex-shrink: 1;
        }
        .vergleich-dashboard.tabelle-dashboard .sort-btn {
            white-space: normal;
            min-width: 0;
            font-size: 0.75rem; /* Touch-Groesse bis 48em (Cross-View 2026-06-26b), vorher nur <=38em */
        }
        .vergleich-dashboard.tabelle-dashboard .tabelle-pager {
            flex: 0 1 auto;
            margin-inline: 0;
        }
        .tabelle-pager-track { display: none; }
        .tabelle-pager-leiste { flex: 0 0 auto; gap: 0; }
        /* 11h: Kurz-Range "X–Y / N" — "Anbieter" und "von" ausgeblendet,
           Slash an. Pfeil-Flaechen schmaler (2.25em breit, Hoehe 3em
           bleibt als Touch-Ziel), Glyph entsprechend kompakter, Gap enger. */
        .tabelle-pager { gap: 0.5em; }
        .tabelle-pager-prefix,
        .tabelle-pager-von-wort { display: none; }
        .tabelle-pager-slash { display: inline; }
        .tabelle-pager-btn { width: 2.25em; height: 3em; }
        .tabelle-pager-glyph { width: 2em; height: 0.7em; }
    }
    /* Sort-Button-Touchgroesse (Cross-View 2026-06-26b): 0.75rem (12px) statt
       var(--text-xs) (11px) ist jetzt in den 48em-Header-Block oben gewandert
       (zusammen mit white-space:normal + min-width:0) — gilt also bis 48em statt
       nur <=38em (Anwender-Entscheidung 2026-06-26: Touch-Pille bis zur kompakten
       Header-Grenze 768px ausdehnen). Auf engen Phones weiterhin Touch-Zweizeiler,
       auf Tablets bis 768px groessere Touch-Flaeche. Haelt Liste<->Tabelle und
       AT<->DE synchron; die DE-Listenansicht fuehrt die Pille im eigenen
       48em-Block ihrer tagesgeld-vergleich.css.
       Einheit `rem` von der Referenz-View (Liste). */
    /* Anlagebetrag-Pills: Layout-Overrides nur unter 52em (Tablet/Mobile-
       Scroll-Strip mit Snap, Masken-Fade, Drag-to-scroll). Auf Desktop
       (>52em) bleibt die Pille auf shared CSS aus `vergleich.min.css`
       (10px/8px-Padding) — sonst entstehen schmalere Pills als in der
       Listenansicht und ein sichtbarer Sprung beim View-Wechsel.
       Schwester-konsistent zum 52em-Block in
       ..\..\Listendarstellung\Tagesgeld DE\tagesgeld-vergleich.css
       (.laufzeit-nav; Schwester-Spiegelung der Tagesgeld-AT-Politur
       2026-05-16d). */
    @media (max-width: 52em) {
        .vergleich-dashboard .laufzeit-nav {
            flex-wrap: nowrap; overflow-x: auto;
            -webkit-overflow-scrolling: touch; scrollbar-width: none;
            scroll-snap-type: x mandatory;
            /* Fallback-Deklaration zuerst (Audit A-7.1 / Nachzug 2026-08-20, Muster aus
               festgeld-tabelle.css): Engines ohne das `safe`-Keyword (WebKit/Safari,
               Chrome < 115) verwerfen die naechste Deklaration komplett. Ohne diese Zeile
               greift dort das zentrale `center` aus vergleich.min.css — bei Overflow werden
               die linken Elemente dann unerreichbar, weil scrollLeft nicht negativ werden
               kann. In Chromium aendert die Zeile nichts: dort gewinnt weiterhin das
               gueltige `safe center` danach. Gehoert mit den Auto-Margins unten zusammen. */
            justify-content: flex-start;
            justify-content: safe center; gap: 0.25em;
            /* Strip-Metrik 1:1 aus tagesgeld-vergleich-core.inc.php uebernommen
               (Cross-View-Nachzug K1-Nachlese, 2026-08-21 — Tagesgeld war das letzte
               Produktpaar ohne diesen Nachzug). `padding` ersetzt das geerbte
               `var(--space-sm)` = 8px aus vergleich.min.css: erst dadurch hat das
               Anlagebetrag-Band im Tablet-Fenster dieselbe Hoehe wie in der Liste
               (~49px statt 59px); unterhalb 48em ersetzt es die dortigen 3px durch den
               gleichwertigen em-Wert. width/max-width geben volle Breite, damit der
               Glasmorphismus-Hintergrund rechts nicht abgeschnitten wird. Die Regel
               steht mehrzeilig wie in der Listen-CSS, damit der Cross-View-Diff der
               beiden Bloecke zeilenweise lesbar bleibt. */
            padding: 0.2em;
            width: 100%;
            max-width: 100%;
        }
        .vergleich-dashboard .laufzeit-nav::-webkit-scrollbar { display: none; }
        /* Auto-Margins als Zentrier-Fallback (Audit A-7.1b / Nachzug 2026-08-20). NICHT
           ENTFERNEN und nicht mit der Fallback-Zeile oben "aufraeumen" — die beiden gehoeren
           zusammen: wo oben flex-start gewinnt, stuende die Leiste sonst auch dann linksbuendig,
           wenn alle Pills in eine Zeile passen. Die Auto-Margins zentrieren genau diesen Fall und
           kollabieren bei Overflow auf 0, die linken Pills bleiben per scrollLeft erreichbar.
           `:first-child`/`:last-child` sind zwingend — `:first-of-type` traefe wegen des gemischten
           Markups (aktive Pill = <span>, uebrige = <a>) ZWEI Elemente und risse die Leiste auseinander. */
        .vergleich-dashboard .laufzeit-nav .laufzeit-pill:first-child { margin-inline-start: auto; }
        .vergleich-dashboard .laufzeit-nav .laufzeit-pill:last-child { margin-inline-end: auto; }
        .vergleich-dashboard .laufzeit-nav .laufzeit-pill {
            min-height: 2.75em; scroll-snap-align: center;
            flex-shrink: 0; padding-left: 0.75em; padding-right: 0.75em;
        }
        .nav-scroll-wrapper {
            -webkit-mask-image: linear-gradient(to right, transparent, black 1.5em, black calc(100% - 1.5em), transparent);
            mask-image: linear-gradient(to right, transparent, black 1.5em, black calc(100% - 1.5em), transparent);
        }
        .nav-scroll-wrapper.scroll-start {
            -webkit-mask-image: linear-gradient(to right, black, black calc(100% - 1.5em), transparent);
            mask-image: linear-gradient(to right, black, black calc(100% - 1.5em), transparent);
        }
        .nav-scroll-wrapper.scroll-end {
            -webkit-mask-image: linear-gradient(to right, transparent, black 1.5em, black);
            mask-image: linear-gradient(to right, transparent, black 1.5em, black);
        }
        .nav-scroll-wrapper.scroll-start.scroll-end { -webkit-mask-image: none; mask-image: none; }
    }
    @media (max-width: 52em) and (hover: hover) and (pointer: fine) {
        .vergleich-dashboard .laufzeit-nav { cursor: grab; }
        .vergleich-dashboard .laufzeit-nav.is-dragging { cursor: grabbing; scroll-behavior: auto; user-select: none; }
        .vergleich-dashboard .laufzeit-nav.is-dragging .laufzeit-pill { pointer-events: none; }
    }
    /* ── Focus-Visible-States fuer Tastatur-Navigation (A1-Nachzug, CT-0148
       2026-08-26) ── Muster 1:1 aus der Schwester-Liste
       (`tagesgeld-vergleich-core.inc.php`, Sammelblock expand-btn/sort-btn/
       details-tab/laufzeit-pill). Der Hell-Modus braucht KEINE eigene Regel:
       `--accent` wird zentral in vergleich.min.css von #A9F6DB auf #00528D
       umgeschrieben (`#vergleich.kontrast-hell .vergleich-dashboard`), der Ring
       wechselt also mit. Zwei verschiedene Gruende, live gemessen 2026-08-26:

       • `.sort-btn` ist ein <button> — der globale `a:focus-visible` aus
         style.css greift dort nicht, es blieb der UA-Ring. Der war NICHT
         barrierefrei kaputt (3,58:1 default / 18,04:1 hell, zweifarbig); die
         Regel ist hier Konsistenz-Politur, keine Fehlerbehebung.
       • `.laufzeit-pill` und `.anbieter-link` sind <a> und erbten deshalb den
         globalen `a:focus-visible{outline:2px solid var(--mint-400)}`. #4DE5B4
         ist eine Dunkelmodus-Farbe, und der Kontrast-Umschalter remappt nur
         `--accent`, nicht `--mint-400`. Im Hell-Modus fiel der Ring damit auf
         1,37:1 (Pill) bzw. 1,40:1 (CTA) — unter der 3:1-Schwelle von WCAG
         1.4.11, also eine echte Verletzung. Mit `--accent` sind es 6,99:1 (Pill)
         bzw. 7,10:1 (CTA).
         Gleicher Mechanismus wie Festgeld Phase A1 (dort 1,45:1). */
    .vergleich-dashboard .sort-btn:focus-visible,
    .vergleich-dashboard .laufzeit-pill:focus-visible,
    .vergleich-dashboard .anbieter-link:focus-visible {
        outline: 2px solid var(--accent, #A9F6DB);
        outline-offset: 0.125em;
    }
    .vergleich-dashboard .filter-section { position: relative; margin-top: -1.1em; margin-bottom: 5em; overflow: visible; }
    .filter-panel-titel {
        display: block;
        font-size: 0.7rem;
        font-weight: 600;
        color: rgba(255, 255, 255, 0.7);
        text-transform: uppercase;
        letter-spacing: 0.5px;
        padding-bottom: 0.5em;
        margin-bottom: 0.75em;
        border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    }
    .eingrenzungsfilter {
        border-top: 1px solid rgba(255,255,255,0.08);
        padding-top: 0.35em;
    }
    .tabelle-wrapper {
        margin-top: 1em;
        position: relative;
        /* Default-Werte fuer --slot-breite/--vp-breite: greifen praktisch nur,
           wenn keine Media-Query matcht (siehe Z. ~840+). Migration vom
           .tabelle-scroller auf .tabelle-wrapper im Zuge der Sticky-Mini-
           Header-Einfuehrung (Politur 2026-05-11), damit der Mini-Track als
           Sibling des Scrollers die Variablen erbt. */
        --slot-breite: 12em;
        --vp-breite: 14em;
    }
    .tabelle-scroller {
        /* Politur 2026-05-11 (Folgepatch): --hdr-logo-h von 11rem auf 12rem
           erhoeht. Begruendung: mit `flex-shrink: 0` am .ab-logo-wrap (siehe
           Z. ~1244) wird das Logo bei langen Anbieter-/Produktnamen nicht mehr
           gestaucht. Damit der Stack `Logo (max 8em) + Anbieter (max 2 Zeilen
           per line-clamp) + Produkt (1 Zeile per line-clamp) + Padding/Gap`
           ohne Ueberlauf in die Badge-Reihe passt, braucht die Reihe 12rem
           statt 11rem (Rechnung: 128 + 30 + 13 + 16 = 187 px ≤ 192 px). */
        --hdr-logo-h: 12rem;
        --hdr-badge-h: 2rem;
        --hdr-zins-h: 3rem;
        --row-data-h: 2.75rem;
        /* Politur 2026-05-10e: eigene Mindesthoehe fuer Bereichstitel-Reihen
           (.ab-gruppe-spacer + button.vp-gruppentitel), getrennt von
           --row-data-h. Auf Desktop deckt 2.75rem (~44 px) den VP-Gruppentitel-
           Button (padding 1.125em + line-height 1.15) — _vpRowSync zwingt sonst
           die VP-Tracks auf einen zu kleinen Wert und der Button overflowt.
           Auf Mobile ist die VP-Spalte display:none, der gleiche 2.75rem-Wert
           gibt den Bereichsbezeichnungen Atemluft ueber dem Toggle-Overlay
           (~30 px Inhalt) und bleibt deutlich kompakter als --row-data-h: 5rem
           (= 80 px Daten-Reihen). */
        --row-titel-h: 2.75rem;
        /* Politur 2026-05-13: Eigene Mindesthoehe fuer CTA-Footer-Reihen
           (Anbieterlinks). 80% von --row-data-h — Anwender-Wunsch: Felder
           mit Anbieterlinks niedriger als die Daten-Reihen, weil sie weniger
           Inhalt tragen und ohne Mini-Label oben keinen extra Padding-Raum
           brauchen. `minmax(--row-cta-h, auto)` laesst die Reihe weiter
           auto-wachsen, falls der Linktext laenger ist als 2.2rem (35 px). */
        --row-cta-h: 2.2rem;
        /* --slot-breite/--vp-breite definiert jetzt der .tabelle-wrapper
           (Politur 2026-05-11, Sticky-Mini-Migration). Default 12em/14em
           und Media-Query-Stufen (Z. ~840+ und Z. ~1700+) wirken via
           Inheritance auf den Scroller, der weiterhin grid-template-columns
           damit baut. Die calc-Logik ist analog zur DE-Hauptnav
           `#nav li { width: 11.111% }` (= 100/9). */
        display: flex;
        flex-direction: row;
        align-items: stretch;
        overflow-x: auto;
        /* Atemluft zwischen letzter Tabellenreihe (CTA-Buttons) und der nativen
           horizontalen Browser-Scrollbar. Padding gehoert zum Scroll-Bereich,
           der native Scrollbar bleibt am Container-Rand — Inhalt rueckt nach oben weg. */
        padding-bottom: 1.6em;
        /* Phase 11 (Politur): Container hat KEINEN eigenen vertikalen Scroll-Port mehr.
           max-height + overflow-y:auto wurden entfernt, weil das Mausrad-Drehen ueber der
           Tabelle den Container vertikal scrollte und die Page nicht. Anwender-Wunsch:
           Mausrad scrollt immer die Page; vertikales In-Tabelle-Scrollen nur explizit
           (Touch/Programmatic). Phase-8-Sticky-Header bleibt im CSS, aber praktisch ohne
           sichtbare Wirkung — der Container scrollt nicht mehr selber. */
        overflow-y: visible;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
        scroll-padding-left: var(--vp-breite, 14em);
        scroll-padding-top: 0.5rem;
        /* Container ohne eigene Hintergrund-Schicht: der Site-Background des
           .vergleich-dashboard scheint durch — Logos und Anbieter fuegen sich
           nahtlos ein (Anwender-Wunsch). Header-Reihen ab-badge/zins/balken und
           VP-Spalte haben weiter eigenen opaken Hintergrund als visuelle
           Strukturierung. */
        background: transparent;
        /* Native horizontale Scrollbar farblich an die Mini-Scrollbar
           (.tabelle-scrollbar-indikator/-thumb) angeglichen — Firefox. */
        scrollbar-color: rgba(255,255,255,0.6) rgba(255,255,255,0.08); /* Kontrast-Politur 2026-06-12 (Schwester-Rollout) */
    }
    /* Vergleichspunkt-Spalte: Flex-Item mit Sticky-Left, eigenes Grid (nicht mehr Subgrid) */
    .vp-spalte {
        flex-shrink: 0;
        width: var(--vp-breite, 14em);
        position: sticky;
        left: 0;
        z-index: 4;
        background: rgba(9, 87, 143, 0.92);
        border-right: 1px solid rgba(255,255,255,0.18);
        box-shadow: 0.25em 0 0.5em rgba(0,0,0,0.2);
        display: grid;
        /* Single-Track-Spalte, die der Outer-Width folgt. Ohne explizite Track-
           Definition fällt der Track auf grid-auto-columns: auto (= max-content)
           zurück — lange Labels weiten den Inner-Track dann über die Outer-
           Width aus. Mobile-Overrides setzen nur `width`, nicht den Track —
           Folge wäre VP-Zellen-Schimmer in die erste Anbieter-Spalte. minmax(0, 1fr)
           bindet den Track an den verfügbaren Platz und cappt min-content. */
        grid-template-columns: minmax(0, 1fr);
        /* Politur 2026-05-10e: --tabelle-data-rows enthaelt die explizite
           Daten-Track-Liste pro sichtbarer Reihe (Server: PHP-Loop ueber $reihen,
           JS-Toggle: updateGridTracks). Fallback ist die alte uniforme repeat()-
           Definition, falls die Variable mal nicht gesetzt ist. */
        grid-template-rows:
            var(--hdr-logo-h)
            var(--hdr-badge-h)
            var(--hdr-zins-h)
            var(--tabelle-data-rows, repeat(var(--anzahl-reihen-rest, 30), minmax(var(--row-data-h), auto)));
    }
    .tabelle-grid {
        flex-shrink: 0;
        display: grid;
        grid-template-columns: repeat(var(--anzahl-anbieter, 8), var(--slot-breite, 12em));
        grid-template-rows:
            var(--hdr-logo-h)
            var(--hdr-badge-h)
            var(--hdr-zins-h)
            var(--tabelle-data-rows, repeat(var(--anzahl-reihen-rest, 30), minmax(var(--row-data-h), auto)));
        align-items: stretch;
    }
    /* Header-Stapel-Reihen — sticky oben, opaker Hintergrund.
       Logo-Reihe hat seit 2026-05-07 einen einfarbigen Hintergrund #0070C0
       (Anwender-Wunsch: Logo-Raender sollen nicht mehr sichtbar sein) —
       siehe eigene Regel weiter unten. badge/zins/balken behalten den
       semitransparenten Block-Background. */
    .vp-zelle.vp-header,
    .ab-zelle[class*="ab-badge"], .ab-zelle[class*="ab-zins"] {
        background: rgba(9, 87, 143, 0.92);
    }
    /* === Phase 8: Sticky-Header oben ===
       position: sticky stand urspruenglich fuer Vertikal-Scrolling im
       Scroll-Container (max-height + overflow-y: auto). Seit Politur
       2026-05-04 / 08l ist der Container ohne eigenen Vertikal-Scrollport
       (overflow-y: visible) — die top-Werte sind also funktional inaktiv.
       position: sticky bleibt trotzdem stehen, weil das ::after-Tooltip an
       .ab-zelle.ab-zins darauf als Containing-Block-Anker angewiesen ist
       (siehe Tooltip-Block weiter unten in dieser Datei,
       .ab-info-tooltip-action); die zugehoerige Funktion infoTooltipSetup steht
       in tagesgeld-tabelle-ui.js. Stolperstein-Pflege fuer kuenftige
       top-Werte: rem-Variablen, niemals em (Phase-2-Stolperstein 3). */
    .ab-zelle.ab-logo,
    .ab-zelle.ab-badge,
    .ab-zelle.ab-zins,
    .vp-zelle.vp-header {
        position: sticky;
        z-index: 3;
    }
    .ab-zelle.ab-badge,
    .vp-zelle.vp-header.vp-badge  { top: var(--hdr-logo-h); }
    .ab-zelle.ab-zins,
    .vp-zelle.vp-header.vp-zins   { top: calc(var(--hdr-logo-h) + var(--hdr-badge-h)); }
    /* Politur 2026-05-20: Mobile Meta-Strip (#NN + Flagge) — auf Desktop
       per Default unsichtbar. Vollstaendige Mobile-Regeln im
       @media-Block (max-width: 38em). */
    .ab-meta-strip { display: none; }
    .ab-zelle.ab-badge { padding-top: 0.25em; padding-bottom: 0.25em; }
    /* Politur 2026-05-07h: Trennlinie zwischen Badge-Reihe und Zins-Reihe
       entfaellt — Inland-/Auslandsanlage-Pille und Zinszahl fliessen optisch
       ineinander. Generelle `.vp-zelle, .ab-zelle { border-bottom: 1px ... }`
       (Z. ~750) bleibt fuer alle anderen Reihen aktiv. */
    .ab-zelle.ab-badge,
    .vp-zelle.vp-header.vp-badge {
        border-bottom: 0;
    }
    /* Vergleichspunkt-Spalte: spezifische Header-Zellen */
    .vp-zelle.vp-header.vp-logo, .vp-zelle.vp-header.vp-badge { font-size: 0.62rem; }
    /* Chart-Icon-Override fuer 'gueltig'-Feld (Standardzins gilt seit) und
       Geschenk-Hover-Override fuer Bonus-Reihe.

       Globale `.icon-chart-area` aus style.css/vergleich.min.css setzt
       font-size: 2.8em + margin-left: -1.8em (gedacht fuer <table>-Detail-
       Tabs). Listenansicht-Schwester nutzt diese Default-Groesse (visuell
       36 px hoch) im `<span class="merkmal-wert">`-Detail-Tab — der
       `margin-left:-1.8em` wird dort durch `.merkmal-wert .icon-chart-area`
       neutralisiert. Politur 2026-05-13: Tabellenansicht uebernimmt
       dieselbe visuelle Groesse und Hover-Farb-/Hintergrund-Logik fuer
       Schwester-Konsistenz. */
    .ab-merkmal-html .icon-chart-area {
        position: relative;
        font-size: 2.8em;
        margin: 0;
        line-height: 1;
        color: #A9F6DB; /* Kontrast-Politur 2026-06-12 (Schwester-Rollout): Akzent-Text #4cb5a0 -> #1FD99B */
        vertical-align: middle;
    }
    /* Politur 2026-06-02: Chart-Glyph-Zustandsfarben an die Listenansicht
       angeglichen (Liste = Master) — Schwester-Rollout des AT-Tabellen-Fix.
       Site-Default `a:focus>.icon, a:hover>.icon { color:#d7f71e }` (style.css
       Z. 238, Spez. 0,2,1) faerbt das Glyph sonst gelb-gruen, sobald der Link
       nach einem Klick den Fokus behaelt — `target="portrait"` oeffnet ein
       zweites Fenster, der Link im Hauptfenster bleibt fokussiert. Die
       Listenansicht neutralisiert das ueber `.merkmal-wert .iframe .icon`
       (0,3,0); wir spiegeln das mit `.ab-merkmal-html .iframe .icon-chart-area`
       (0,3,0): focus/active/visited bleiben auf der Grundfarbe #4cb5a0, NUR
       hover hebt mit accent-light hervor (hover-Regel 0,3,1 schlaegt die
       Schutzregel 0,3,0 source-order-unabhaengig). :visited braucht keine
       eigene Regel — kein `a:visited>.icon` in der Site-CSS. */
    .ab-merkmal-html .iframe .icon-chart-area {
        color: #A9F6DB; /* Kontrast-Politur 2026-06-12 (Schwester-Rollout) */
    }
    .ab-merkmal-html a:hover > .icon-chart-area {
        color: #DFFDF2; /* Kontrast-Politur 2026-06-12 (Schwester-Rollout): Hover-Ton der Akzentfamilie */
    }
    /* Site-Default `a:hover { background: #6699CC; padding: 1px 0 }` aus
       style.css/vergleich.min.css greift sonst und faerbt den Bereich
       hinter Chart-Icon/Geschenk-Link hellblau. Listenansicht-Schwester
       neutralisiert das ueber `.merkmal-wert a:hover { background: none;
       padding: 0 }`; wir reproduzieren es im `.ab-merkmal-html`-Scope. */
    .ab-merkmal-html a:hover,
    .ab-merkmal-html a:focus,
    .ab-merkmal-html a:visited {
        background: none;
        padding: 0;
    }
    /* Geschenk-IMG-Hover (Bonus-Reihe, cardgift-m.svg in `<a class="cardgifta">`):
       Site-Default `a.cardgifta:hover img { filter: brightness(120%) sepia(100%)
       saturate(300%) hue-rotate(15deg) }` schiebt das gruene Icon ins Gelbe.
       Listenansicht-Schwester ueberschreibt mit `brightness(1.4) saturate(1.5)`
       (nur Aufhellung, Tuerkis bleibt). Wir uebernehmen denselben Override. */
    .ab-merkmal-html a.cardgifta:hover img {
        filter: brightness(1.12);
    }
    /* Geschenk-Icon-Vergroesserung (Bonus-Reihe): Site-Default
       `a.cardgifta img { width: 2.7em }` aus style.css um 10 % anheben,
       Politur 2026-05-20. Greift nur fuer Inline-Geschenke in der Bonus-
       Reihe; der Tooltip-Action-Variant `a.ab-info-tooltip-action.cardgifta
       img` (Z. ~1818, fixe 1.5em) bleibt unberuehrt. */
    .ab-merkmal-html a.cardgifta:not(.ab-info-tooltip-action) img {
        width: 2.97em;
    }
    /* Phase 14 (A7): Truncate-Spans und Info-Icon — Default Desktop sichtbar
       der Volltext, Kurz-Variante und Info-Icon ausgeblendet. Mobile-Switch
       weiter unten im 38em-Block. */
    .ab-merkmal-voll { display: inline; }
    .ab-merkmal-kurz { display: none; }
    /* Tooltip fuer Info-Icon (Mobile-Truncate). Wird per JS-IIFE
       `infoTooltipSetup()` an document.body angehaengt. */
    .ab-info-tooltip {
        display: none;
        position: absolute;
        z-index: 200;
        max-width: 18em;
        padding: 0.5em 0.75em;
        background: rgba(15, 20, 30, 0.95);
        color: #fff;
        font-size: 0.75rem;
        font-weight: 400;
        line-height: 1.4;
        border-radius: 0.4em;
        box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.35);
        pointer-events: auto;
        /* Politur 2026-05-20b: Tooltip-Inhalt rechtsbuendig — konsistent
           zur Anwender-Konvention "alle Vergleichsangaben rechtsbuendig"
           in der Tabellenansicht. Plain-Text-Span erbt text-align,
           Action-Zeile staut per `justify-content: flex-end`. */
        text-align: right;
    }
    .ab-info-tooltip.is-visible { display: block; }
    /* Politur 2026-05-20 (Bonus-Tooltip-Action): Action-Zeile mit Geschenk-
       Icon + Linktext im Tooltip-Body, dargestellt unter dem Plain-Text-
       Volltext, durch border-top getrennt. Nur fuer Bonus-Felder mit DB-
       Geschenk-Link gerendert (siehe `infoTooltipSetup.show()` —
       `btn.dataset.giftHref`-Check). Action-Container ist ein `<a class=
       "iframe cardgifta ab-info-tooltip-action" target="portrait">`, der
       per Fancybox-Bind die Aktionsbeschreibung modal oeffnet. Tap-Target-
       Mindesthoehe 2.75em ≈ 44 px bei 16-px-Base. Hover-Filter spiegelt
       das Inline-Verhalten aus `.ab-merkmal-html a.cardgifta:hover img`. */
    .ab-info-tooltip-text { display: block; }
    /* Selektor-Verlaengerung auf `a.ab-info-tooltip-action.cardgifta` —
       der Action-Link traegt absichtlich die Klasse `cardgifta` (fuer den
       Fancybox-Bind und visuelle Konsistenz mit dem Inline-Icon), lebt
       aber als Body-Child ausserhalb des `.ab-merkmal-html`-Scopes, in
       dem die DE-Listen-typischen `a:hover/`:visited`-Resets greifen.
       Ohne Verlaengerung wuerden drei Site-Defaults durchschlagen:
       (a) `a.cardgifta:hover img { filter: brightness(120%) sepia(100%)
       saturate(300%) hue-rotate(15deg) }` (0,2,2) wuerde das Icon im
       Hover gelb-orange statt aufgehellt-tuerkis faerben; (b) `a:hover {
       padding: 1px 0 }` (0,1,1) wuerde das Base-Padding ueberschreiben
       und einen Hoehen-Sprung erzeugen; (c) `a:visited` (0,1,1) koennte
       `color: #fff` aushebeln. Mit `a.ab-info-tooltip-action.cardgifta`
       liegt die Base-Spezifizitaet bei (0,2,1) > Site-Defaults, mit
       `:hover img` bei (0,3,2) > (0,2,2). Befund aus Regelwaechter #14. */
    a.ab-info-tooltip-action.cardgifta {
        display: flex;
        align-items: center;
        /* Politur 2026-05-20b: Inhalt rechtsbuendig stauen — Reihenfolge
           bleibt Icon-Label-Pfeil, alles ruckt nach rechts (konsistent zur
           text-align: right des Containers). Label-Span verliert flex:1
           und schrumpft auf natuerliche Breite mit Umbruch-Erlaubnis. */
        justify-content: flex-end;
        gap: 0.5em;
        margin-top: 0.5em;
        padding-top: 0.5em;
        padding-bottom: 0.25em;
        border-top: 1px solid rgba(255, 255, 255, 0.18);
        color: #fff;
        text-decoration: none;
        /* WCAG-Fix 2026-05-20c: rem statt em — der Tooltip-Container traegt
           `font-size: 0.75rem` (= 12 px), `2.75em` waere damit nur ~33 px.
           `2.75rem` ist unabhaengig vom Container-font-size und liefert
           stabile 44 px = WCAG-2.5.5-Tap-Target. */
        min-height: 2.75rem;
        font-weight: 500;
    }
    a.ab-info-tooltip-action.cardgifta img {
        width: 1.5em;
        height: 1.5em;
        flex-shrink: 0;
    }
    a.ab-info-tooltip-action.cardgifta span:not(.ab-info-tooltip-arrow) { flex: 0 1 auto; }
    .ab-info-tooltip-arrow { margin-left: 0.25em; opacity: 0.85; }
    a.ab-info-tooltip-action.cardgifta:hover,
    a.ab-info-tooltip-action.cardgifta:focus-visible {
        background: rgba(255, 255, 255, 0.08);
        border-radius: 0.25em;
    }
    a.ab-info-tooltip-action.cardgifta:hover img,
    a.ab-info-tooltip-action.cardgifta:focus-visible img {
        filter: brightness(1.12);
    }
    /* Mobile: schmaler padden, kleinere Schrift. */
    @media (max-width: 38em) {
        .tabelle-fussnoten {
            padding: 0.875em 1em;
            font-size: 0.8rem;
        }
    }
    /* Responsive */
    @media (max-width: 52em) {
        /* Politur 2026-05-09: --slot-breite und --vp-breite werden ab dem
           38.0625em-Block (oben) per calc((100vw - 3em) / 4) gesetzt — hier
           nur Font-Size/Padding-Politur fuer Tablet/kleinere Notebooks.
           Vorher: --slot-breite: 10em und --vp-breite: 12em fix; das fuehrte
           zu 2-4 sichtbaren Anbietern je nach Bruchteil und nicht zur klaren
           3-Anbieter-Stufung. */
        .vp-zelle, .ab-zelle { font-size: 0.78rem; padding: 0.4375em 0.5em; }
        .ab-zelle.ab-zins { font-size: 1.25rem; }
    }
    /* Mobile-Hauptblock (Politur 2026-05-08, Phase 14, weiter angepasst in
       Folgepatch 14c):
       Drei Anbieter-Spalten mit je 1/3 Viewport. VP-Spalte ist auf Mobile
       komplett unsichtbar (`display: none`) — die Reihen-Labels uebernehmen
       die Mini-Labels, die Bereichsbezeichnungen rendern in der ersten
       Anbieter-Spalte (siehe Mini-Label-Block plus mb-gruppentitel-Block
       weiter unten). `--vp-breite: 0px` bleibt fuer die Variable, weil
       `.tabelle-scroller { scroll-padding-left: var(--vp-breite, 14em); }`
       sie verwendet — `0px` vermeidet ein vp-Breite-grosses Snap-Padding,
       das sonst die linkste Spalte zu weit nach rechts wegschneiden wuerde
       (Stolperstein 13). --hdr-logo-h auf 8rem statt 11rem reduziert die
       Logo-Reihe. font-size/padding-Werte aus dem alten 38em-Block uebernommen.
       Die alte 29em-Stufe (3-Slot-Layout fuer Smartphones im Hochkant) entfaellt,
       weil dieses Mobile-Layout ohnehin durchgaengig 3 Spalten zeigt.

       Vertikal-Scroll-Port (Phase 14, A2) entfaellt im Folgepatch 08l
       (2026-05-08): Auf Anwender-Wunsch hat die Tabelle auf Mobile keinen
       eigenen Y-Scrollbalken mehr — `max-height`, `overflow-y: auto` und
       `overscroll-behavior-y` wurden entfernt. Die Tabelle wird in voller
       Hoehe sichtbar und ueber den Page-Scrollbar erreicht.
       Politur 2026-05-11: Der frueher hier verankerte Mini-Sticky-Header
       (`.tabelle-scroller.is-mini`) ist durch den externen, fixed-positio-
       nierten Sticky-Mini-Header (.tabelle-sticky-mini) ersetzt — siehe
       eigener CSS-Block weiter unten in dieser Datei. */
    @media (max-width: 38em) {
        .tabelle-wrapper {
            /* Politur 2026-05-08h (B1): Anbieter-Spalten auf 30vw reduziert
               (vorher calc((100vw - 0.5em) / 3) ≈ 33.3vw). Bei 375 px
               Viewport ergibt 30vw = 112.5 px je Spalte; 3 Spalten = 337.5 px.
               Plus Site-Container-Offset (~21 px) plus rechte Schimmer-Gradient/
               Scrollbar (~12 px) bleiben rund 5 px Atemluft — drei Anbieter-
               Spalten passen jetzt vollstaendig in den Viewport, das vorherige
               Anschneiden der dritten Spalte am rechten Rand entfaellt.
               Politur 2026-05-11 (P1): von Viewport-vw auf Scroller-clientWidth
               umgestellt. 30vw rechnete gegen den Viewport, der Scroller-
               Container ist wegen Site-Section-Padding aber schmaler als
               100vw — auf einem Samsung S25 (~393 px Viewport, ~343 px
               Scroller-clientWidth) ueberhing die 3. Anbieter-Spalte um
               ~10-15 px nach rechts (Logos, Flaggen-Pille, "AG"-Suffix
               und Texte sichtbar abgeschnitten). `--scroller-w` wird per
               IIFE auf scroller.clientWidth gesetzt UND zusaetzlich am
               Wrapper gespiegelt (tabelleMiniLabelSetupIIFE/syncBreite),
               damit auch der .tabelle-sticky-mini-track als Wrapper-
               Descendant denselben Wert erbt.
               Politur 2026-05-11 (Sticky-Mini-Migration): Selektor vom
               .tabelle-scroller auf .tabelle-wrapper umgestellt (CSS-Custom-
               Properties vererben nur an Descendants, der Sticky-Mini-Track
               als Sibling des Scrollers brauchte den gemeinsamen Vorfahren). */
            --slot-breite: calc((var(--scroller-w, 100vw) - 1.5em) / 3);
            --vp-breite: 0px;
        }
        .tabelle-scroller {
            /* Politur 2026-05-08e (P1): --hdr-logo-h von 8rem auf 10rem
               erhoeht — bei der bisherigen 8rem-Reihe wurde das Logo
               (max-height 8em ≈ 5.76rem bei 0.72rem font-size) plus
               Anbietername (0.78rem * 1.2 line-height) plus Produktname
               (0.7rem * 1.15 line-height) am oberen Rand abgeschnitten,
               weil der Stack flex-flex-start arbeitet und keine Atemluft
               oben hatte. 10rem (~160 px) gibt dem Logo + 2 Textzeilen
               sauberen Platz, das Logo wird nicht mehr beschnitten.
               Politur 2026-05-11 (Folgepatch): von 10rem auf 11rem
               erhoeht. Logo-Wrap ist jetzt flex-shrink: 0 (siehe
               Z. ~1244), das Logo wird nicht mehr gestaucht — bei
               Mobile-30vw-Spalten gerendert mit ~100 px Hoehe. Stack:
               100 + 30 (Anbieter 2-Zeilen-Clamp) + 13 (Produkt
               1-Zeile-Clamp) + 16 (Padding/Gap) = 159 px, passt in
               11rem (176 px) ohne Ueberlauf in die Badge-Reihe. */
            --hdr-logo-h: 11rem;
            /* Politur 2026-05-20c: Badge-Reihe (Inland/Auslandsanlage-Pille)
               auf Mobile komplett aus dem Layout nehmen. Die alte Pille wandert
               als Flagge in den .ab-meta-strip in der linken oberen Ecke der
               Logo-Zelle (Positionsnummer + Landesflagge). Track-Hoehe auf 0px
               setzt die Subgrid-Reihe inaktiv; .ab-zelle.ab-badge wird im
               Mobile-Block weiter unten zusaetzlich auf padding/min-height/
               overflow kollabiert. */
            --hdr-badge-h: 0px;
            /* Folgepatch 14d: --row-data-h auf Mobile von 2.75rem auf 5rem
               erhoeht. Mehrzeilige Werte (Einlagensicherung, Hoechsteinlage,
               PostIdent/VideoIdent, Zinsausschuettungs-Sonderfaelle) brauchen
               bei 122-px-Spaltenbreite und 12.8-px-Mini-Label-Reservierung
               (padding-top: 1.7em) mehr Platz, sonst ueberragen sie die
               44-px-Cell-Box visuell. 5rem = 80 px abzueglich padding ergibt
               etwa 54 px Inhaltsraum (~3-3.5 Textzeilen); `minmax(min, auto)`
               im Subgrid laesst die Reihe bei laengeren Inhalten weiter
               auto-wachsen. */
            --row-data-h: 5rem;
            /* Politur 2026-05-10e: Spacer-Reihen auf Mobile etwas hoeher als
               Desktop (Toggle-Overlay 30 px + Atemluft). Default 2.75rem
               (~44 px) wirkte noch knapp, 3rem (~48 px) gibt dem Banner sicht-
               bare Luft und bleibt deutlich kompakter als --row-data-h: 5rem
               (~80 px Daten-Reihen). VP-Spalte ist auf Mobile display:none —
               der VP-Gruppentitel-Button spielt keine Rolle. */
            --row-titel-h: 3rem;
            /* Politur 2026-05-13: CTA-Footer-Reihe auf Mobile von 5rem
               (--row-data-h) auf 4rem reduziert — 80% (Anwender-Wunsch).
               Inner-Link (font-size 0.7rem, padding 0.4375em) plus Zellen-
               padding 0.625em ergibt ca. 37-40 px Inhaltshoehe — passt
               bequem in 64 px (4rem). minmax laesst auch hier auto-Wachstum
               zu, wenn der CTA mehr Hoehe braucht. */
            --row-cta-h: 4rem;
            /* Politur 2026-05-11 (M2): Scroll-Snap auf Mobile abschalten. Der
               x-proximity-Snap des Default-Blocks cappte das echte
               scrollLeft-Maximum um ~14 px, sodass die letzte Anbieter-Spalte
               rechts angeschnitten blieb. Auf Touch ist Snap ohnehin eher
               hinderlich (schwungvolles Drag-Scrolling springt zurueck).
               scroll-padding-right schiebt zusaetzlich den Atemraum zum
               Schimmer-Gradient ein. */
            scroll-snap-type: none;
            scroll-padding-right: 0.5em;
        }
        /* Politur 2026-05-11 (P3): column-gap zwischen Anbieter-Spalten auf
           Mobile. Auf Smartphones (Samsung S25-Screenshots) stiessen die
           Spalten ohne sichtbaren Abstand aneinander, Texte (z.B.
           "Einlagensicherung AUSTRIA Ges.m.b.H.") wirkten ineinander
           uebergehend. Subgrid uebernimmt nur Tracks, nicht Gaps — die
           Reihen-Sync zwischen VP-Spalte und Anbieter-Spalten bleibt
           intakt. --slot-breite (P1) kompensiert die 2 × 0.5em-Gaps via
           1.5em-Reserve. */
        .tabelle-grid { column-gap: 0.5em; }
        /* Politur 2026-05-11 (P2): Schimmer-Gradient auf Mobile schmaler und
           halbtransparent. Default 2em × opacity 1 wirkte auf 30vw-Spalten
           als heller Streifen ueber fast einem Drittel der letzten Spalte —
           im Samsung-Screenshot als "Schattierung am rechten Rand der
           Bereiche-Banner" beanstandet. Auf Touch ist Drag-Scrolling auch
           ohne visuellen Scroll-Hinweis intuitiv, der Schimmer kann dezenter
           bleiben. ::before bleibt am Default-opacity-0 (linker Schimmer
           wird erst per .is-scroll-anfang aktiv), nur der dann sichtbare
           Wert wird angepasst. */
        .tabelle-wrapper::after,
        .tabelle-wrapper::before { width: 0.75em; }
        .tabelle-wrapper::after { opacity: 0.5; }
        .tabelle-wrapper.is-scroll-anfang::before { opacity: 0.5; }
        .vp-zelle, .ab-zelle { font-size: 0.72rem; padding: 0.375em 0.4375em; }
        .ab-zelle.ab-zins { font-size: 1.05rem; }
        /* Politur 2026-05-10f: 0.2em Abstand zwischen Zins-Header-Reihe und
           erstem Bereich (MERKMALE-Bezeichnung). Grid-Default `align-self:
           stretch` macht die Zinszelle 0.2em kuerzer als ihre fixe Track-Hoehe
           (--hdr-zins-h: 3rem), die Differenz wirkt als Luecke direkt unter
           dem Zinszahl-Block. Nur auf Mobile — auf Desktop kleben Header und
           Bereichstitel weiter direkt aneinander. */
        .ab-zelle.ab-zins,
        .vp-zelle.vp-header.vp-zins {
            margin-bottom: 0.2em;
        }
        .ab-cta-link { font-size: 0.7rem; padding: 0.4375em 0.625em; }
        /* Politur 2026-05-08e (P1): Logo-Stack vertikal zentrieren, damit
           das Logo nicht oben am Rand klebt. justify-content: center auf
           der flex-direction:column-Zelle zentriert vertikal Logo + Anbieter-
           name + Produktname als Block in der 10rem-Reihe — das Logo bekommt
           damit oben automatisch Atemluft. */
        .ab-zelle.ab-logo {
            justify-content: center;
        }
        /* Sticky-Header-Reaktivierung: Background der Sticky-Zellen muss
           solid sein, sonst scheint die scrollende Datenreihe darunter durch.
           Site-Site-Variable `--bg-card` wird hier wegen Subgrid-Hintergrund-
           Vererbung explizit als solid `#0a3a5c`-Aequivalent ausgedrueckt. */
        .ab-zelle.ab-badge,
        .ab-zelle.ab-zins,
        .vp-zelle.vp-header.vp-badge,
        .vp-zelle.vp-header.vp-zins {
            background: rgb(9, 87, 143);
        }
        /* Phase 14 (A3): Mini-Label als Banner ueber jeder Wert-Reihe.
           padding-top reserviert Platz, der Inhalt darunter bleibt zentriert.
           Mini-Label ist position: absolute — keine zusaetzliche Grid-Reihe,
           daher bleiben _vpRowSync und Track-Hoehen unangetastet
           (Stolperstein 12 vermieden). gruppe-zu wirkt durch das Eltern-
           opacity automatisch auch auf das Label.
           Folgepatch 14a-5: font-size von 0.6rem auf 0.7rem (~11.2 px),
           padding-top der Eltern-Zelle von 1.55em auf 1.7em entsprechend
           nachgezogen. Sekundaerer Text traegt damit ueber dem WCAG-
           Mindestwert von 11 px.
           Politur 2026-05-14 (Pass 1+2, Schwester-Sync zu Festgeld AT):
           padding-top um 0.3em auf 2em erhoeht — Pass 1 brachte 1.7em →
           1.9em, Pass 2 nach Live-Verifikation 1.9em → 2em. Der :has()-
           Override fuer truncated Labels wandert parallel auf 2.8em
           (Pass 1: 2.5em → 2.7em, Pass 2: 2.7em → 2.8em). */
        .ab-zelle.ab-merkmal {
            padding-top: 2em;
            /* Politur 2026-05-13: Trennlinie nach jedem Paar aus Mini-Label
               und Datenzeile (Anwender-Wunsch). Default
               `.vp-zelle, .ab-zelle { border-bottom: 1px solid rgba(255,255,255,0.06) }`
               (Z. ~1082) ist zu zart — auf 0.14 verstaerkt (gleiche Staerke
               wie die Trennlinie zur Vorgruppe am .ab-gruppe-spacer border-top).
               Subgrid-Reihen-Subgrid: die Border fluchtet horizontal ueber
               alle drei Anbieter-Spalten zu einer durchgehenden Linie. */
            border-bottom: 1px solid rgba(255, 255, 255, 0.14);
        }
        /* Politur 2026-05-11 (Mini-Label-Truncate, Visual-Pass): bei Reihen
           mit sichtbarem Volltext-Button (`.is-truncated`) waechst das
           Mini-Label-Banner von ~20 auf ~30 px durch den groesseren Button.
           padding-top adaptiv per :has() von 1.7em auf 2.5em hochziehen,
           damit der Banner-Bereich kollisionsfrei zum Wert-Bereich endet.
           Reihen ohne Truncate-Button (kurze Labels, Banner bleibt schmal)
           behalten die schmale Reservierung — verhindert ueberfluessigen
           Leerraum bei kurzen Bezeichnungen. :has() ist seit Chrome 105 /
           Safari 15.4 / Firefox 121 stabil verfuegbar.
           Politur 2026-05-14 (Pass 1+2, Schwester-Sync zu Festgeld AT):
           +0.3em parallel zur Basis-Regel (oben). Pass 1: 2.5em → 2.7em,
           Pass 2 nach Live-Verifikation: 2.7em → 2.8em. */
        .ab-zelle.ab-merkmal:has(.ab-info-icon-mini-label.is-truncated) {
            padding-top: 2.8em;
        }
        /* Politur 2026-05-13: border-bottom der letzten merkmal-Zelle einer
           Gruppe unterdruecken, weil der direkt nachfolgende .ab-gruppe-spacer
           selbst eine border-top: 1px solid rgba(255,255,255,0.14) traegt
           (Default-Regel Z. ~1462). Ohne dieses Override summieren sich
           beide Linien zu einer optischen 2 px-Doppellinie am Gruppen-
           Uebergang. `:has(+ .ab-gruppe-spacer)` greift nur dann, wenn der
           DIREKTE DOM-Sibling ein gruppe-spacer ist — also genau bei der
           letzten merkmal-Zelle vor jedem Bereichstitel-Wechsel.
           Browser-Support analog zur Truncate-:has()-Regel oben. */
        .ab-zelle.ab-merkmal:has(+ .ab-gruppe-spacer) {
            border-bottom: none;
        }
        /* Folgepatch 14b: Pro Wert-Reihe nur EIN Mini-Label, mittig ueber die
           drei sichtbaren Anbieter-Spalten. Verankert in der ersten Anbieter-
           Spalte (DOM-first-child), absolut positioniert mit Viewport-Breite,
           horizontal per JS sticky am linken Viewport-Rand (siehe IIFE
           tabelleMiniLabelSetup, Variable --mini-label-x). Andere Anbieter-
           Spalten rendern weiter ein <span class="ab-mini-label"> im HTML
           (Render-Symmetrie, kein PHP-Index-Param noetig), das aber per
           Default-Mobile-Display:none unsichtbar bleibt. */
        .ab-mini-label { display: none; }
        .tabelle-grid > .anbieter-spalte:first-child .ab-mini-label {
            /* Politur 2026-05-11 (Mini-Label-Truncate): display: flex statt
               block. Damit Text-Span und Volltext-i-Button als Flex-Children
               nebeneinander zentriert sitzen koennen. Ellipsis-Eigenschaften
               (white-space/overflow/text-overflow) wandern auf .ab-mini-
               label-text — der Container kuemmert sich nur um Breite,
               Position und Sticky-Sync. */
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 0.25em;
            position: absolute;
            /* Politur 2026-05-13: 0.2em Abstand zur Top-Kante der Datenzelle
               (Anwender-Wunsch) — Label klebt nicht mehr direkt an der
               Trennlinie der Vorgaenger-Zeile. em bezieht sich auf die
               eigene Schriftgroesse 0.8rem ≈ 12.8 px, ergibt ca. 2.6 px
               Abstand. */
            top: 0.2em;
            left: 0;
            /* Politur 2026-05-10e: Breite an die tatsaechlich sichtbare
               Tabellen-Breite gebunden (`--mini-label-w`, gesetzt von der
               IIFE `tabelleMiniLabelSetupIIFE` als `min(scroller.clientWidth,
               grid.offsetWidth)`). Der Scroller ist wegen Section-Padding
               schmaler als 100vw — vorher ragte das Mini-Label rechts ueber
               die letzte Anbieter-Spalte hinaus. Fallback auf den alten
               100vw-Wert, falls die IIFE nicht laeuft. */
            width: var(--mini-label-w, calc(100vw - 0.5em));
            box-sizing: border-box;
            padding: 0.15em 0.5em;
            font-size: 0.8rem;
            line-height: 1.25;
            /* Politur 2026-05-11 (Label-Hierarchie): Label-Schrift von
               0.78 → 0.55 Deckkraft gedimmt. Damit die Werte in den
               Daten-Zellen die dominantere Schriftfarbe sind und die
               Mini-Labels als sekundaere Tonstufe zuruecktreten
               (Anwender-Wunsch 2026-05-11). Gleiche Farb-Familie wie die
               Werte (reines Weiss), nur Helligkeit reduziert — keine
               eigene Toenung. */
            color: rgba(255, 255, 255, 0.55);
            /* Politur 2026-05-13: Hintergrund von var(--bg-card) auf transparent
               umgestellt (Anwender-Wunsch) — Mini-Label teilt jetzt den Page-
               Hintergrund mit der Datenzelle darunter, beide wirken als eine
               durchgehende Flaeche. Vorher (08e/P2) war hier var(--bg-card) als
               einheitliche Header-System-Optik gemeinsam mit .ab-gruppe-spacer
               und .ab-cta gesetzt. Trennung zur naechsten Reihe sitzt jetzt
               an .ab-zelle.ab-merkmal border-bottom (1 px, 0.14 Opacity). */
            background: transparent;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            text-align: center;
            /* Politur 2026-05-11 (Mini-Label-Truncate): white-space, overflow
               und text-overflow wandern auf das innere .ab-mini-label-text.
               Der Container ist jetzt Flex — Ellipsis greift am Inner-Span,
               der per `min-width: 0` schrumpfen darf.
               Politur 2026-05-13: border-bottom entfernt — die Linie zwischen
               Label und Wert ist nicht mehr gewuenscht (Anwender-Wunsch:
               Label und Wert als zusammengehoeriges Paar). Trennung zur
               naechsten Reihe sitzt jetzt an .ab-zelle.ab-merkmal border-
               bottom. */
            border-bottom: none;
            /* Politur 2026-05-11 (Mini-Label-Truncate): `pointer-events: none`
               entfernt. Mini-Label traegt selbst keinen Click-Handler — die
               Eigenschaft war eine Vorbeugung ohne sichtbares Verhalten,
               blockierte aber Click-Events des Inline-i-Buttons in manchen
               Browser-/Touch-Konstellationen (Anwender-Meldung: Hand-Cursor
               sichtbar, Klick reagierte nicht). Ohne diese Eigenschaft
               faengt der Button seine eigenen Klicks regulaer ueber die
               Event-Delegation in `infoTooltipSetup()`. */
            /* Politur 2026-05-11 (A): translateX → translate3d zwingt den
               Browser, das Element auf eine eigene GPU-Compositor-Layer zu
               promoten. Touch-Scrolling laeuft auf dem Compositor-Thread; ohne
               eigenen Layer wird der translateX-Update vom Main-Thread
               (CSS-Custom-Property setzen → Style-Recalc → Paint) 1-2 Frames
               verzoegert sichtbar — der User berichtete ein "Springen" der
               Legende beim horizontalen Daumen-Scroll. backface-visibility
               ist ein zusaetzlicher Compositor-Hint, der das Layer-Promote
               noch deterministischer macht. */
            transform: translate3d(var(--mini-label-x, 0px), 0, 0);
            backface-visibility: hidden;
            will-change: transform;
            /* Politur 2026-05-11 (Mini-Label-Truncate, Hit-Test-Fix):
               z-index: 2 ueber den nachfolgenden Anbieter-Spalten-Geschwistern
               (die per DOM-Order ohne explizites z-index stapeln). Hintergrund:
               das Mini-Label-Banner sitzt absolute in der first-child-Anbieter-
               Spalte und wird per `transform: translate3d(--mini-label-x)`
               visuell ueber alle drei Spalten gezogen. Ohne z-index lag das
               Banner im Stacking-Kontext der first-child-Spalte und wurde von
               second/third-child `.ab-zelle.ab-merkmal` (jeweils
               position: relative, z-auto) im Hit-Test ueberlagert — Klicks
               auf den Inline-i-Button landeten in der jeweils darunter-
               liegenden Wert-Zelle statt am Button. Unter dem Sticky-Header
               (z-index: 3) und ueber den Geschwistern (z-auto) ist `2` die
               richtige Stufe. Analog am `.mb-gruppentitel`-Bereichstitel-
               Toggle (gleiche transformierte Banner-Mechanik). */
            z-index: 2;
        }
        /* Politur 2026-05-11 (Mini-Label-Truncate): Inner-Span traegt die
           Ellipsis-Eigenschaften, die zuvor am Container lagen. min-width: 0
           ist Pflicht, damit der Flex-Child wirklich schrumpfen kann
           (Default min-width: auto an Flex-Items = min-content) — sonst
           greift text-overflow: ellipsis nicht. flex: 0 1 auto erlaubt das
           Schrumpfen, behaelt aber die Content-Breite als Bevorzugung,
           damit kurze Labels nicht den Platz fuellen. */
        .ab-mini-label-text {
            min-width: 0;
            flex: 0 1 auto;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        /* Folgepatch 14c: VP-Spalte auf Mobile komplett unsichtbar.
           Reihen-Labels uebernehmen die Mini-Labels in der ersten Anbieter-
           Spalte (siehe oben), Bereichsbezeichnungen mit Toggle rendern
           als zweite Form/Button-Pair in der .ab-gruppe-spacer (siehe
           weiter unten). VP-Drawer-Mechanik ist komplett rueckgebaut. */
        .vp-spalte { display: none; }

        /* Phase 14 (A6): CTA Icon-only auf Mobile.
           SVG sichtbar, Text ausgeblendet, 48-px-Tap-Target via min-w/h.
           Spezifizitaet `.vergleich-dashboard .anbieter-link` schlaegt
           das Listen-globale Styling aus vergleich.min.css. */
        /* Politur 2026-05-10d: Rechteckiger Button mit zwei Fontello-Icons
           (Bank + Externer-Link-Pfeil) — exakt wie die alte Tabellenansicht.
           Override gegen `.icon`-Defaults aus style.css (font-size: 3em;
           position: absolute; margin-left: -1.6em) und `.icon-bank`-Mobile-
           Override (position: absolute) per hoeherer Spezifizitaet
           (`.vergleich-dashboard .anbieter-link i.icon-bank` = 3 Klassen + 1 Tag). */
        .vergleich-dashboard .anbieter-link {
            display: flex;
            align-items: center;
            justify-content: center;
            min-width: 4rem;
            min-height: 2rem;
            padding: 0.25rem 0.5rem;
            gap: 0.25rem;
        }
        .vergleich-dashboard .anbieter-link i.icon-bank,
        .vergleich-dashboard .anbieter-link i.icon-link-ext {
            display: inline-block;
            position: relative;
            top: 0;
            font-size: 1.25rem;
            margin: 0;
            line-height: 1;
            color: inherit;
            width: auto;
            height: auto;
        }
        .vergleich-dashboard .anbieter-link-text {
            display: none;
        }
        /* Phase 14 (A7): Mobile-Switch fuer Truncate. Volltext aus, Kurzform
           plus Info-Icon ein. Info-Icon mit ausreichend grosser Hitbox. */
        .ab-merkmal-voll { display: none; }
        .ab-merkmal-kurz { display: inline; }
        /* Politur 2026-05-19 (Bonus-Mobile-Truncate): Bonus-Reihe auf Mobile
           auf 6 Zeilen kappen (Folge-Patch 2026-05-19: von 5 auf 6 Zeilen
           hochgezogen, weil mehrzeilige Sonderzins-Beschreibungen sonst zu
           frueh getruncated wurden). Der DE-Spitzenreiter (CosmosDirekt)
           fuehrt eine mehrzeilige Sonderzins-Beschreibung, die ueber Subgrid-
           Reihen-Sync alle Anbieter-Spalten auf >300 px Hoehe blaeht und
           Leerflaeche zwischen "Zinsgutschrift" und Bereichstitel "Merkmale"
           erzeugt. line-height 1.5 × 6 Zeilen = 9em max-height + overflow:
           hidden. `.ab-bonus { position: relative }` als Anker fuer den
           rechts-unten platzierten Info-Icon. JS-IIFE `tabelleBonusTruncate-
           Setup` setzt `.is-truncated` am Icon UND am Container, wenn
           scrollHeight > clientHeight; `infoTooltipSetup` zeigt den
           Plain-Text-Volltext. Spezifizitaet `.ab-zelle.ab-bonus
           .ab-info-icon-bonus` (0,3,0) schlaegt das generische
           `.ab-info-icon` (0,1,0) und positioniert den Button neu ohne
           `!important`.

           Folge-Patch 2026-05-19: `padding-bottom: 1.8em` am inneren Span
           bei `.is-truncated`-Container reserviert Platz fuer den absolut-
           positionierten Info-Icon (1.4em breit + 0.4em Abstand zu Rand
           = ~1.8em). Ohne diesen Padding-Block ueberlagerte das Icon bei
           textgefuellten Zellen die letzte Zeile. Die Container-Klasse
           `.is-truncated` wird parallel zur Icon-Klasse in der IIFE
           gesetzt (siehe `tabelleBonusTruncateSetupIIFE`). */
        .ab-zelle.ab-bonus { position: relative; }
        .ab-zelle.ab-bonus .ab-merkmal-html {
            display: block;
            max-height: 9em;
            line-height: 1.5;
            overflow: hidden;
        }
        /* Politur 2026-05-19 (Bonus-Truncate Mobile): Reserve am unteren
           Span-Rand bei `.is-truncated`, damit der absolut-positionierte
           i-Button bottom-right nicht die letzte Text-Zeile ueberlagert.
           1.8em = 1.4em Icon-Hoehe + 0.4em Abstand zum Rand. */
        .ab-zelle.ab-bonus.is-truncated .ab-merkmal-html {
            padding-bottom: 1.8em;
        }
        .ab-zelle.ab-bonus .ab-info-icon-bonus { display: none; }
        /* Politur 2026-05-20b: i-Button im Truncate-Zustand bekommt einen
           Markenblau-Spot mit Backdrop-Blur, damit er den Bereich fuer
           sich beansprucht und nicht unschoen ueber der letzten sichtbaren
           Text-Zeile haengt (Screenshot-Befund 2026-05-20). Markenton
           #0070C0 mit 85% Opacity laesst den Blur durchscheinen; Border-
           Radius 50% macht den Button kreisrund passend zum Glyph. Hoehere
           Spezifizitaet (0,4,0) als Default `.ab-info-icon` (0,1,0)
           schlaegt dessen `background: transparent` ohne `!important`. */
        .ab-zelle.ab-bonus .ab-info-icon-bonus.is-truncated {
            display: inline-flex;
            position: absolute;
            right: 0;
            bottom: 0.2em;
            margin-left: 0;
            background-color: rgba(0, 112, 192, 0.85);
            /* Anwender-Tweak nach 20b: Sehr leichter Blur (0.05em ≈
               Sub-Pixel) — der Markenblau-Spot bleibt deutlich, der
               Hintergrund-Inhalt wird kaum verfremdet. Webkit- und
               Standard-Property sind symmetrisch, damit Safari/iOS und
               Chrome/Firefox dasselbe Bild liefern. */
            -webkit-backdrop-filter: blur(0.05em);
            backdrop-filter: blur(0.05em);
            border-radius: 0%;
            color: #fff;
        }
        .ab-info-icon {
            position: relative;
            /* Politur 2026-05-11 (M1b): eigener Stacking-Kontext, damit der
               unsichtbare `::before`-Slop im Hit-Test ueber dem textfuehrenden
               Eltern-DIV `.ab-zelle.ab-merkmal` liegt. Ohne diesen Kontext
               lieferte `elementFromPoint(iconCx, iconY ± 5)` die Elternzelle
               statt des Icons — die vertikale Slop-Region war faktisch
               wirkungslos (VRT-Befund 2026-05-11 C2). */
            isolation: isolate;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.4em;
            height: 1.4em;
            margin-left: 0.35em;
            padding: 0;
            /* Politur 2026-05-11 (i-Buttons transparent): Anwender-Wunsch —
               i-Buttons generell ohne eigenen Hintergrund. Glyph + Hand-
               Cursor tragen das visuelle Feedback. */
            background: transparent;
            color: rgba(255, 255, 255, 0.85);
            border: none;
            border-radius: 50%;
            /* Politur 2026-05-11 (M1b): Icon visuell verdoppelt — 0.85em → 1.7em
               Schrift, width/height von 1.4em skaliert mit auf ~27 px Visual
               (vorher ~14 px). Anwender meldete, dass das Icon zu klein zum
               Erkennen sei. Doppelte Schrift macht das ⓘ-Glyph deutlich
               sichtbar; bei `--row-data-h: 5rem` (80 px) und 30vw-Spalten
               (~112 px) bleibt im Layout genug Platz fuer Text + Icon. */
            font-size: 1.7em;
            line-height: 1;
            cursor: pointer;
            vertical-align: baseline;
        }
        /* Folgepatch 14a-1: Pseudoelement-Slop fuer 44-px-Tap-Target.
           Politur 2026-05-11 (M1b): Slop in max(em, rem)-Mix umgestellt, damit
           er bei Icon-font-size-Aenderungen nicht ueberproportional waechst —
           der absolute rem-Boden deckelt die em-Berechnung. Hitbox bleibt
           damit unabhaengig vom Icon-Visual-Faktor in einem stabilen Korridor
           (Visual + 2 × Slop): bei 1.7em-Icon ≈ 27 + 28 = 55 px vertikal,
           27 + 25 = 52 px horizontal — sicher ueber dem 44-px-AAA-Wert.
           Plus z-index: 1 im neuen Stacking-Kontext des Icons (siehe
           `isolation: isolate` oben) — Slop liegt im Hit-Test ueber der
           Eltern-Zelle, der vertikale Tap-Lift wirkt jetzt auch praktisch. */
        .ab-info-icon::before {
            content: '';
            position: absolute;
            top: max(-1.4em, -0.875rem);
            bottom: max(-1.4em, -0.875rem);
            left: max(-1.25em, -0.78125rem);
            right: max(-1.25em, -0.78125rem);
            z-index: 1;
        }
        .ab-info-icon:hover,
        .ab-info-icon:focus-visible {
            color: #fff;
        }
        .ab-info-icon:focus-visible {
            outline: 2px solid var(--accent, #A9F6DB);
            outline-offset: 2px;
        }
        /* Politur 2026-05-11 (Mini-Label-Truncate): Volltext-Button im Mini-
           Label. Spezifizitaet `.ab-info-icon.ab-info-icon-mini-label` (0,2,0)
           schlaegt die generische `.ab-info-icon`-Regel (0,1,0) im Mobile-
           Block. Default unsichtbar — JS-IIFE `tabelleMiniLabelTruncateSetup`
           setzt `.is-truncated`, sobald die Text-Span-Ellipsis gegriffen hat
           (`text.scrollWidth > text.clientWidth`). font-size kleiner als der
           generische 1.7em-Icon, weil das Mini-Label nur 0.8rem traegt —
           ein 1.7em-Button waere zu hoch fuer das schmale Banner. Hitbox-
           Slop entsprechend reduziert. background: transparent — Anwender-
           Wunsch 2026-05-11 (i-Buttons generell ohne eigenen Hintergrund);
           der ⓘ-Glyph plus Hand-Cursor traegt das visuelle Feedback. */
        .ab-info-icon.ab-info-icon-mini-label {
            display: none;
            /* Politur 2026-05-11 (Mini-Label-Truncate, Visual-Pass):
               font-size: 2em statt 1em — Anwender-Wunsch: i-Button im
               Mini-Label-Banner doppelt so gross, damit er in etwa die
               Groesse der Merkmal-Truncate-Buttons (`.ab-info-icon` Mobile,
               font-size: 1.7em an 0.85rem-Schrift) erreicht. width/height
               von 1.2em auf 1em reduziert — kompakterer Quad (25.6 × 25.6 px
               statt 30.7 × 30.7 px), Glyph fuellt die Box. Damit die Banner-
               Hoehe nur moderat (~30 px statt ~35 px) waechst und nicht zu
               sehr in den Werte-Bereich der Zelle ragt. */
            font-size: 2em;
            width: 1em;
            height: 1em;
            margin-left: 0;
            background: transparent;
            /* Politur 2026-05-11 (Mini-Label-Truncate, Visual-Pass): Idle-Color
               an die Mini-Label-Schriftfarbe `rgba(255,255,255,0.55)`
               (Regel .ab-mini-label weiter oben in dieser Datei)
               angeglichen — Anwender-Wunsch: der Button soll farblich nicht
               heller als der Label-Text wirken. Hover/Focus boostet weiter
               auf #fff als Feedback. */
            color: rgba(255, 255, 255, 0.55);
        }
        .ab-info-icon.ab-info-icon-mini-label.is-truncated {
            display: inline-flex;
        }
        .ab-info-icon.ab-info-icon-mini-label::before {
            /* Slop kleiner als generisches Icon — ~28 px Hitbox bei
               ~12 px Visual. Wert in max(em, rem) analog zu generischem
               Icon, aber etwa halbiert. Slop reicht weiter als die
               Banner-Hoehe, was OK ist: nur der Klick zaehlt, nicht das
               visuelle Pseudoelement. */
            top: max(-0.8em, -0.5rem);
            bottom: max(-0.8em, -0.5rem);
            left: max(-0.6em, -0.4rem);
            right: max(-0.6em, -0.4rem);
        }
        .ab-info-icon.ab-info-icon-mini-label:hover,
        .ab-info-icon.ab-info-icon-mini-label:focus-visible {
            color: #fff;
        }
        /* Politur 2026-05-20c: Mobile-Erscheinungsbild der oberen linken Ecke
           wird vom Meta-Strip uebernommen. Runder Desktop-Pos-Badge
           (.ab-pos-badge) und die Inland/Auslands-Pille (.ab-badge-pill)
           werden mobile ausgeblendet — der Strip vereint beide Aussagen
           (#NN-Nummer + Landesflagge) am Logo-Kopf. Vorher (Phase 14 A8 +
           Politur 2026-05-08f N3) war die Pille hier zu einer reinen
           Flag-Pille umformatiert; diese Doppelinformation entfaellt jetzt.
           Die Subgrid-Track-Hoehe der Badge-Reihe ist parallel ueber
           `--hdr-badge-h: 0px` (oben im Mobile-Variablen-Block) hoehenfrei;
           die Zelle selbst kollabiert hier zusaetzlich (padding 0,
           min-height 0, overflow hidden), damit kein blaues Restband
           zwischen Logo- und Zins-Reihe stehen bleibt. Inhalt der Pille
           per display: none inaktiv — die Inland/Ausland-Information
           wandert in den Strip.
           Containing-Block fuer den absoluten Strip ist .ab-zelle.ab-logo
           (position: sticky an Z. ~1131 → bildet Containing-Block).
           pointer-events: none verhindert, dass der Strip Klicks auf den
           darunterliegenden .ab-logo-link blockiert. */
        .ab-zelle.ab-badge {
            padding: 0;
            min-height: 0;
            overflow: hidden;
        }
        .ab-pos-badge { display: none; }
        .ab-badge-pill { display: none; }

        .ab-meta-strip {
            display: flex;
            align-items: center;
            gap: 0.35em;
            position: absolute;
            top: 0.4em;
            left: 0.4em;
            z-index: 2;
            pointer-events: none;
            line-height: 1;
        }
        .ab-meta-pos {
            font-size: 0.7rem;
            font-weight: 600;
            color: rgba(255, 255, 255, 0.92); /* Kontrast-Politur 2026-06-12 (Schwester-Rollout): 0.6 -> 0.92 */
            letter-spacing: 0.02em;
            line-height: 1;
            font-variant-numeric: tabular-nums;
            /* Platz fuer "#NN" reservieren — bleibt auch bei Sport-Ranking-Tie
               (gleicher Zins wie Vorgaenger, $rang leer) erhalten, damit die
               Flagge in allen Spalten an derselben x-Position startet. Wert
               so gewaehlt, dass zweistellige Nummern sicher passen
               (`#99` ≈ 1.55em). */
            min-width: 1.7em;
            display: inline-block;
        }
        .ab-meta-flag {
            display: inline-flex;
            align-items: center;
            line-height: 1;
        }
        .ab-meta-flag .flag-img-variant {
            width: auto;
            height: 0.85rem;
        }
        .ab-meta-flag .flag-emoji-variant {
            font-size: 1.05rem;
            line-height: 1;
        }
        /* Folgepatch 14c: Bereichsbezeichnung mit Toggle in der ersten
           Anbieter-Spalte. Der Button wird in der .ab-gruppe-spacer-Reihe
           absolut positioniert (volle Viewport-Breite), nutzt dieselbe
           --mini-label-x-Variable wie das Mini-Label fuer den Sticky-Sync
           am linken Viewport-Rand. min-height an allen .ab-gruppe-spacer,
           damit die Subgrid-Reihe Platz fuer den Button reserviert (Subgrid
           uebernimmt die maximale Reihen-Hoehe ueber alle Anbieter-Spalten,
           also wirkt das min-height ueber alle drei sichtbaren Spalten). */
        .tabelle-grid .ab-gruppe-spacer {
            min-height: 2.5em;
        }
        .tabelle-grid > .anbieter-spalte:first-child .ab-gruppe-spacer {
            position: relative;
        }
        .tabelle-grid > .anbieter-spalte:first-child .mb-gruppentitel {
            display: flex;
            position: absolute;
            top: 0;
            left: 0;
            /* Politur 2026-05-10e: Breite an die tatsaechlich sichtbare
               Tabellen-Breite gebunden (siehe Kommentar an .ab-mini-label
               weiter oben). */
            width: var(--mini-label-w, calc(100vw - 0.5em));
            box-sizing: border-box;
            /* Politur 2026-05-11 (A): translate3d + backface-visibility analog
               zum .ab-mini-label-Block (siehe oben). Erzwingt eigene
               GPU-Compositor-Layer, sodass der Bereichsbezeichnungs-Toggle
               nicht hinter dem Touch-Scroll herhinkt. */
            transform: translate3d(var(--mini-label-x, 0px), 0, 0);
            backface-visibility: hidden;
            will-change: transform;
            /* Politur 2026-05-11 (Mini-Label-Truncate, Hit-Test-Fix):
               analog zum .ab-mini-label-Block — z-index 2 ueber den
               nachfolgenden Spalten-Geschwistern, damit der Bereichstitel-
               Toggle-Button im transformierten Banner-Bereich klickbar
               bleibt (Vorbeugung gegen den Stacking-Konflikt, den Anwender
               am Mini-Label-Volltext-Button gemeldet hat). */
            z-index: 2;
            /* z-index/translate3d sind die Sticky-Sync-Mechanik (Banner folgt
               dem Horizontal-Scroll). Padding und Chevron-Position liegen in
               der .mb-gruppentitel-Regel unten (space-between, padding-right
               5% — Chevron am rechten Banner-Rand). */
        }
        /* Politur 2026-05-13 / Redesign 2026-06-19: Bereichstitel-Optik auf
           Mobile — Hintergrund auf transparent (selbe Farbe wie die
           Vergleichskriterien-Zellen, die ebenfalls keinen expliziten
           Background haben und auf den dunklen Page-Hintergrund durch-
           scheinen; der Default-Block liefert die Koernungs-Flaeche darunter).
           Label (links) und einzelner SVG-Chevron (rechts) sitzen per
           space-between an den Banner-Raendern — der fruehere gepunktete
           Fueller und das +/−- bzw. ▼-Glyph sind entfernt. Trennlinie zur
           vorigen Gruppe liefert jetzt die .ab-gruppe-spacer-Koernung
           (border-top); die Button-eigene Border bleibt hier ausgeschaltet,
           damit auf Mobile nur eine durchgehende Bandflaeche liest. */
        .tabelle-grid > .anbieter-spalte:first-child .mb-gruppentitel {
            background: transparent;
            border-top: none;
            border-bottom: none;
            /* Politur 2026-05-14 (Pass 1+2, Schwester-Sync zu Festgeld AT):
               Inneres Padding asymmetrisch — Pass 1 setzte 2.5%/2.5%
               (konsistent zur 2.5%-Site-Konvention `.result-count
               { padding-left: 2.5% }`, `.sort-buttons { margin-right:
               2.5% }`). Pass 2 nach Live-Verifikation: Anwender hat
               `padding-right: 5%` nachverlangt. `padding-left: 2.5%` bleibt
               — die Beschriftung sass schon richtig. Die Asymmetrie 2.5%/5%
               wirkt jetzt ueber den per space-between rechtsbuendigen Chevron
               (Default-Caret-Regel): der grosszuegigere Rechtsabstand haelt
               den Chevron etwas vom Banner-Rand weg. Prozentwerte beziehen
               sich auf die Banner-Breite (`--mini-label-w` =
               `min(scroller.clientWidth, grid.offsetWidth)`). */
            padding-left: 2.5%;
            padding-right: 5%;
        }
        /* Hover (2026-06-19b): Koernung bleibt unveraendert; der Chevron hellt
           auf (wie Desktop). Touch-Geraete zeigen kaum Hover. */
        .tabelle-grid > .anbieter-spalte:first-child .mb-gruppentitel:hover .vp-gruppentitel-caret {
            color: #BFDBEF;
        }
        /* Redesign 2026-06-19: Der fruehere Mobile-Transparent-Reset der
           .ab-gruppe-spacer ist entfallen — auf Mobile gilt jetzt dieselbe
           Koernungs-Flaeche wie auf Desktop (Default-Block oben), sodass das
           Band auch auf kleinen Displays als eigene Struktur liest. */
        /* Mobile-Chevron etwas groesser fuer bessere Tap-Sichtbarkeit auf
           kleinen Displays (Desktop nutzt die 15px aus dem SVG-Attribut). */
        .tabelle-grid > .anbieter-spalte:first-child .mb-gruppentitel .vp-gruppentitel-caret svg {
            width: 18px;
            height: 18px;
        }
    }
    /* Mini-Scrollbar-Indikator (Frage 20 = C) */
    .tabelle-scrollbar-indikator {
        position: relative;
        height: 0.25em;
        margin: 0.5em 0.25em 0;
        background: rgba(255,255,255,0.08);
        border-radius: 999px;
        overflow: hidden;
        transition: opacity 150ms ease;
    }
    .tabelle-scrollbar-thumb {
        position: absolute;
        top: 0;
        left: var(--thumb-x, 0%);
        height: 100%;
        width: var(--thumb-width, 100%);
        background: rgba(255,255,255,0.6); /* Kontrast-Politur 2026-06-12 (Schwester-Rollout): 0.4 -> 0.6 */
        border-radius: inherit;
    }
    @media (hover: hover) and (pointer: fine) {
        .tabelle-scrollbar-thumb { transition: background 125ms ease; }
        .tabelle-scroller:hover ~ .tabelle-scrollbar-indikator .tabelle-scrollbar-thumb,
        .tabelle-scroller.is-dragging ~ .tabelle-scrollbar-indikator .tabelle-scrollbar-thumb {
            background: rgba(255,255,255,0.75); /* Kontrast-Politur 2026-06-12 (Schwester-Rollout): Hover mit angehoben */
        }
    }
    .ab-mini-logo {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        max-height: 6em;
        max-width: 100%;
    }
    @media (max-width: 38em) {
        /* Mobile: VP-Spalte ist display:none — kein Container-Offset noetig
           (JS liefert vpBreitePx = 0). Mini-Spalten in der Breite des
           3-Anbieter-Mobile-Grids; column-gap muss zum Original-Grid passen
           (Z. ~1770) — sonst driften Mini-Spalten gegen Original-Spalten
           beim Horizontal-Scroll (~5.75 px/Spalte Versatz, vom visuellen
           Regressionstest 2026-05-11 detektiert).
           Politur 2026-05-12: font-size der Mini-Spalte auf 0.72rem (analog
           Mobile-`.ab-zelle`, Z. ~1785). Damit ergibt `max-height: 6em` am
           .ab-mini-logo die gleiche relativen Skalierung wie auf Desktop —
           ~69 px Logo-Hoehe (6 * 0.72rem). */
        .tabelle-sticky-mini-track {
            column-gap: 0.5em;
        }
        .anbieter-spalte-mini {
            font-size: 0.72rem;
            padding: 0.375em 0.4375em;
        }
    }
    /* DE-spezifisch: Erfahrungsberichte-Reihe — DB-HTML rendert
       `<a class="iframe"><i class="icon icon-chat-empty"></i></a>` (Sprechblasen-
       Icon, Link zum Bewertungs-Iframe). Globale `.icon { position: absolute;
       font-size: 3em; margin-left: -1.6em; color: #b5ce24 }` aus style.css
       (Z. ~290) muss neutralisiert werden, sonst rutscht das Icon nach unten
       (statische position-absolute-Box) und uebernimmt die Site-Linkfarbe
       Limettengruen (#b5ce24, geerbt ueber `a:link`). Analog `.icon-chart-area`-
       Override fuer `gueltig`-Feld (Z. ~1712). `max-height` deckelt die
       Glyphen-Box auf der Zellen-Breite, damit das Icon auf groesseren
       Anbieter-Spalten nicht ueberproportional waechst. */
    .tabelle-dashboard .ab-merkmal-html .icon-chat-empty {
        position: relative;
        display: inline-block;
        font-size: 2.73em;
        max-height: 2.73em;
        margin: 0;
        line-height: 1;
        color: #A9F6DB; /* Kontrast-Politur 2026-06-12 (Schwester-Rollout): Akzent-Text #4cb5a0 -> #1FD99B */
        vertical-align: middle;
    }
    .tabelle-dashboard .ab-merkmal-html a:hover > .icon-chat-empty {
        color: #DFFDF2; /* Kontrast-Politur 2026-06-12 (Schwester-Rollout): Hover-Ton der Akzentfamilie */
    }

    /* Sonderzinsen — Balken-Indikator: Hoehe waechst (8px -> 13px) */
    .vergleich-dashboard .balken-toggle-bars-grow { align-items: flex-end; height: 0.8125em; margin-bottom: 0.0625em; }
    .vergleich-dashboard .balken-toggle-bars-grow .balken-toggle-bar {
        flex: none; width: 0.3125em; height: 0.5em; border-radius: 0.0625em;
        background: rgba(4,36,64,0.42); transition: height 0.2s ease, background 0.2s ease;
    }
    .vergleich-dashboard .balken-toggle[data-state="on"] .balken-toggle-bars-grow .balken-toggle-bar { height: 0.8125em; background: #DCEBF8; }

    /* Touch-Geraete (kein Hover): Umschalt-Hinweis nicht einblenden, damit die
       Sprechblase nach dem Antippen nicht stehen bleibt. Maus-Hover und Tastatur-
       Fokus (:focus-visible) zeigen den Hinweis weiterhin. */
    @media (hover: none) {
        .vergleich-dashboard .balken-toggle[data-tooltip]:hover::after { opacity: 0; }
    }

    /* Mobile (gestapelt): groesserer Abstand ueber den Toggle-Baendern, optisch wie
       der Abstand zwischen Laufzeit- und Anlagebetrag-Band (ca. --space-lg). */
    @media (max-width: 48em) {
        .vergleich-dashboard .filter-section .sonderzins-filter-group,
        .vergleich-dashboard .filter-section .ausland-filter-group { margin-top: var(--space-sm); }
    }

    @media (prefers-reduced-motion: reduce) {
        .vergleich-dashboard .balken-toggle-bar,
        .vergleich-dashboard .balken-toggle-arrow { transition: none; }
    }
    /* ── Europakarte (Länderfilter) ── */
    /* display:flex (column) ueberschreibt das auto-fit-Grid der zentralen .filter-row —
       sonst laegen .ek-kopf und .ek-spalten als Grid-Items nebeneinander. */
    /* Buehne: eine Nuance dunkler als das mittelblaue Panel (rgba(9,87,143)),
       aber bewusst NICHT navy-dunkel — der urspruengliche Handelsblatt-Ton war
       fuer die Seite zu dunkel (Anwender-Feedback 2026-07-07). min-height
       gibt der Karte (meet, zentriert) Raum, damit sie als Buehne wirkt.
       Full-Bleed (2026-07-09): margin -1.5em = horizontales Padding der
       .anpassen-panel — die Buehne laeuft bis an die Panelkante, nur der
       hell→dunkel→hell-Uebergang bleibt sichtbar; deshalb keine Rundung und
       keine Seiten-Border. Das horizontale Padding gleicht die 1.5em wieder
       aus, damit die Inhalte buendig zu den uebrigen Panel-Zeilen stehen. */
    .vergleich-dashboard .ek-sektion { position: relative; overflow: hidden; margin-left: -1.5em; margin-right: -1.5em; padding: var(--space-md) calc(var(--space-md) + 1.5em); background: linear-gradient(160deg, rgba(10,48,82,0.88), rgba(14,64,108,0.78)); border: 1px solid var(--border); border-left: 0; border-right: 0; min-height: 27em; display: flex; flex-direction: column; justify-content: center; }
    .ek-kopf { flex: 0 0 auto; }
    /* Karte liegt hinter den Spalten; Wrapper faengt keine Klicks, aber die
       Landflaechen/Marker schon — so klicken freie Flaechen zu den Checkboxen durch. */
    .ek-karte-wrap { position: absolute; inset: 0; z-index: 0; pointer-events: none; display: flex; align-items: center; justify-content: center; }
    .ek-karte-wrap svg { width: 100%; height: 100%; }
    .ek-karte-wrap .ek-land, .ek-karte-wrap .ek-marker { pointer-events: auto; }
    .ek-kopf, .ek-spalten { position: relative; z-index: 1; }
    /* Die vollbreiten Container fangen sonst Klicks im freien Korridor ab —
       durchlassen, nur ihre Inhalte (Pills, Zaehler, Glas-Spalten) fangen. */
    .ek-kopf, .ek-spalten { pointer-events: none; }
    .ek-kopf > *, .ek-spalten .filter-column { pointer-events: auto; }
    /* Karten-Zustaende (Land-Stroke = Buehnenfarbe, wirkt als Laendergrenze) */
    .ek-silhouette path { fill: rgba(255,255,255,0.07); }
    .ek-land { fill: rgba(255,255,255,0.2); stroke: rgba(10,48,82,0.9); stroke-width: .5; cursor: pointer; transition: fill var(--transition-base), filter var(--transition-base); }
    .ek-land.ek-gewaehlt { fill: var(--primary); filter: drop-shadow(0 0 6px rgba(0,112,192,0.55)); }
    .ek-land:not(.ek-gesperrt):not(.ek-gewaehlt):hover { fill: rgba(0,112,192,0.45); }
    .ek-land.ek-gesperrt { fill: rgba(255,255,255,0.02); cursor: default; }
    .ek-marker { fill: rgba(255,255,255,0.14); stroke: rgba(255,255,255,0.55); stroke-width: .5; cursor: pointer; transition: fill var(--transition-base), filter var(--transition-base); }
    .ek-marker.ek-gewaehlt { fill: var(--primary); filter: drop-shadow(0 0 6px rgba(0,112,192,0.55)); }
    .ek-marker:not(.ek-gesperrt):not(.ek-gewaehlt):hover { fill: rgba(0,112,192,0.45); }
    .ek-marker.ek-gesperrt { fill: rgba(255,255,255,0.05); cursor: default; }
    /* Sanfter Puls beim Zustandswechsel (JS setzt .ek-pop kurz) */
    @keyframes ekPop { 0% { opacity: .55; } 100% { opacity: 1; } }
    .ek-pop { animation: ekPop 250ms ease; }
    /* Kopf: nur noch Schnellauswahl + Zaehler. Der Gruppen-Umschalter liegt
       nicht mehr hier, sondern auf den Glas-Karten selbst (.ek-spalte) —
       die aktive Karte zeigt, was die Karte gerade darstellt. */
    .ek-kopf { display: flex; flex-wrap: wrap; gap: .5em .75em; margin-bottom: .75em; align-items: center; }
    .ek-presets { display: inline-flex; flex-wrap: wrap; gap: .3em; align-items: center; }
    .ek-presets-label { color: var(--text-secondary); font-size: .75em; margin-right: .2em; }
    .ek-preset-btn {
        cursor: pointer; font: inherit; font-size: .75em;
        padding: .3em .85em; border-radius: 1.4em; color: rgba(255,255,255,0.85);
        background: transparent; border: 1px solid rgba(255,255,255,0.3);
        transition: background var(--transition-base), border-color var(--transition-base);
    }
    .ek-preset-btn:hover { background: rgba(169,246,219,0.25); border-color: rgba(169,246,219,0.5); }
    .ek-zaehler { color: var(--text-secondary); font-size: .85em; margin-left: auto; align-self: center; }
    /* Checkbox-Spalten als Glas ueber der Karte */
    /* Mittel-Korridor zwischen den Spalten: die Karte (meet, zentriert) wird
       dort sichtbar — Kerneuropa liegt genau in der Mitte. */
    .ek-spalten { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(2em, 24%, 16em); row-gap: var(--space-md); }
    /* Bewusst duenn (Alpha .26, blur 1px), damit die Karte durchscheint. */
    .ek-spalten .filter-column { background: rgba(10,48,82,0.26); backdrop-filter: blur(1px); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: .75em; }
    /* Die Karten SIND der Gruppen-Umschalter: ganze Flaeche aktivierbar.
       Aktiv-Markierung = dasselbe Muster wie die gewaehlte Laufzeit im
       "alle Zinsen"-Tab (.zins-item.highlight): Akzent-Border + transparente
       Akzentflaeche. */
    .ek-spalte { cursor: pointer; transition: background var(--transition-base), border-color var(--transition-base); }
    .ek-spalte:not(.ek-spalte-aktiv):hover { border-color: rgba(255,255,255,0.35); }
    .ek-spalten .ek-spalte-aktiv { background: rgba(169,246,219,0.15); border-color: var(--accent); }
    /* Karten-Titel als echter Button (Tastatur-Zugang zum Umschalten),
       optisch unveraendert — der .filter-label-Span behaelt den zentralen Stil. */
    .ek-spalte-kopf { display: block; width: 100%; background: none; border: none; padding: 0; margin: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; }
    /* Glas-Karten trennen sich selbst — zentrale Separator-Raender/-Margins neutralisieren
       (die frueheren .filter-row-separator[style]-Regeln greifen ohne Inline-style nicht mehr). */
    .ek-spalten .filter-column-separator { margin: 0; }
    /* Tooltip */
    .ek-tooltip { position: absolute; z-index: 2; pointer-events: none; background: rgba(10,37,64,0.92); color: #fff; padding: .3em .6em; border-radius: .4em; font-size: .8em; white-space: nowrap; opacity: 0; transition: opacity 150ms ease; }
    .ek-tooltip.ek-sichtbar { opacity: 1; }
    /* Tablet-Zwischenbereich (50–64em): die Tafeln sind wegen des Karten-
       Korridors schmal — Checkboxen einspaltig, sonst laeuft das zentrale
       repeat(2,1fr)-Grid ueber den Tafelrand (VRT-Befund 2026-07-07). */
    /* Untere Kante 50.01em statt 50em (Audit A-7.2 / Phase K6, Rollout Tagesgeld
       CT-0148 2026-08-26): exakt 800px traf sonst diesen Block UND den
       `max-width: 50em`-Block darunter gleichzeitig. */
    @media (min-width: 50.01em) and (max-width: 64em) {
        .ek-spalten .checkbox-group-wrap { grid-template-columns: 1fr; }
    }
    /* Schmale Viewports: Spalten untereinander, Karte wird dezente Textur.
       Gleicher Breakpoint wie die alte Sitz-Zeile (50em). */
    @media (max-width: 50em) {
        .ek-spalten { grid-template-columns: 1fr; }
        .ek-karte-wrap { opacity: .18; }
    }

    /* === Hochkontrast-Hell-Modus — Ebene C =================================
       Aktiv nur bei #vergleich.kontrast-hell. Der KERN liegt seit v=18 ZENTRAL
       in vergleich.min.css: Toggle-Basis (.kontrast-zeile/.kontrast-toggle inkl.
       .ecke-*, Hover/Focus/aria-pressed, Mobile-Position), Ebene A (Karte/h1/
       #hilfe .icon-Kette/Toggle-Hell), Ebene B (.vergleich-dashboard-Variablen-
       Remap) und der geteilte Mobile-Anteil (Karte randlos + 50vw-box-shadow +
       mobile #hilfe .icon). Hier stehen NUR die DE-Tabellen-spezifischen
       Uebersteuerungen hartkodierter Farben. Alle Overrides per Spezifitaet ueber
       den ID+Klasse-Praefix (schlaegt vergleich.min.css/tabelle.min.css) — NIE
       !important, em-Konvention (px nur border-width/box-shadow/outline/gradient/
       @media), keine Geometrie-/transform-Aenderung (FLIP unberuehrt), G1-Heatmap-
       Logik hier gegenstandslos (DE-DOM hat keine Heatmap). Akzente konsequent
       Blau statt Tuerkis/Gruen. Bewusste Ausnahmen: (1) die drei Kopf-Baender
       (Logo / Inland-Ausland-Badge / Zins) UND die Sticky-VP-Label-Spalte bleiben
       Marken-Blau (DE-Entscheidung: das blaue Label-Band bleibt in BEIDEN Modi
       stehen; die VP-Spalte wird nur OPAK gesetzt, damit die weisse Karte nicht
       durchscheint — die vp-zelle-Labels bleiben weiss); Schrift auf den Baendern
       explizit weiss. (2) Die Europakarte-Buehne im Filter-Panel bleibt bewusst
       dunkel — der Guard am Blockende setzt die durchschlagenden Hell-Werte dort
       lokal zurueck. (3) Dunkle Tooltip-Bubbles (.ab-info-tooltip) bleiben dunkel. */

    /* -- Sticky-VP-Label-Spalte kippt auf WEISS mit dunkler Schrift (wie AT/Festgeld-DE);
          NUR die Kopf-Baender bleiben opak Marken-Blau (eigener Block unten). Daten-
          Zellen (ab-zelle) auf der weissen Karte bekommen blau getoente Trennkanten. -- */
    #vergleich.kontrast-hell .vp-spalte { background: #F7F9FC; border-right-color: rgba(0,82,141,0.28); box-shadow: 0.25em 0 0.5em rgba(0,82,141,0.10); }
    #vergleich.kontrast-hell .vp-zelle { color: #003A66; background: #F7F9FC; }
    #vergleich.kontrast-hell .vp-zelle, #vergleich.kontrast-hell .ab-zelle { border-bottom-color: rgba(0,82,141,0.12); }
    #vergleich.kontrast-hell .ab-merkmal.ab-leer { color: rgba(0,0,0,0.65); }

    /* -- Kopf-Baender (Inland-Ausland-Badge / Zins) + VP-Header-Zellen: bewusste
          Marken-Blau-Ausnahme. Da die VP-Body-Spalte oben auf Weiss kippt, die drei
          Header-Reihen explizit OPAK rgb(9,87,143) zuruecksetzen (0.92-Alpha wuerde
          die weisse Karte durchscheinen lassen); Spezifitaet .vp-zelle.vp-header
          (1,3,0) + Quellreihenfolge schlagen die generische vp-zelle-Weiss-Regel.
          Schrift auf den Baendern weiss (VP-Header, Anbietername, Zinszahl). Die
          Logo-Reihe traegt eigenes #0070C0 (Basis) -> unveraendert. -- */
    #vergleich.kontrast-hell .vp-zelle.vp-header,
    #vergleich.kontrast-hell .ab-zelle.ab-badge,
    #vergleich.kontrast-hell .ab-zelle.ab-zins { background: rgb(9,87,143); }
    #vergleich.kontrast-hell .vp-zelle.vp-header { color: rgba(255,255,255,0.9); }
    #vergleich.kontrast-hell .ab-anbieter { color: #fff; }
    #vergleich.kontrast-hell .ab-zelle.ab-zins { color: #fff; }

    /* -- Chart-/Chat-Glyphen (icon-chart-area 'gueltig'-Feld + icon-chat-empty):
          Tuerkis (#A9F6DB/#DFFDF2) -> Blau (Ruhe/Fokus #00528D, Hover #0070C0). -- */
    #vergleich.kontrast-hell .ab-merkmal-html .icon-chart-area,
    #vergleich.kontrast-hell .ab-merkmal-html .iframe .icon-chart-area { color: #00528D; }
    #vergleich.kontrast-hell .ab-merkmal-html a:hover > .icon-chart-area { color: #0070C0; }
    #vergleich.kontrast-hell .tabelle-dashboard .ab-merkmal-html .icon-chat-empty { color: #00528D; }
    #vergleich.kontrast-hell .tabelle-dashboard .ab-merkmal-html a:hover > .icon-chat-empty { color: #0070C0; }

    /* -- Geschenk-Icon (cardgift-Icon, Bonus-Reihe): DE-Basis nutzt nur Hover-
          brightness(1.12), keine Ruhe-Farbfilterung. Im Hell-Modus die Tuerkis-
          Quelle per Filterkette (brightness(0) macht sie quellfarben-unabhaengig)
          auf Marken-Blau ziehen; EIGENER Hover, weil filter NICHT additiv ist
          (der Basis-Hover wuerde die Kette sonst ersetzen). Der Tooltip-Action-
          Variant lebt in der dunklen Bubble (document.body) -> hier nicht getroffen. -- */
    #vergleich.kontrast-hell .ab-merkmal-html a.cardgifta img {
        filter: brightness(0) saturate(100%) invert(26%) sepia(98%) saturate(946%) hue-rotate(176deg) brightness(110%) contrast(113%);
    }
    #vergleich.kontrast-hell .ab-merkmal-html a.cardgifta:hover img {
        filter: brightness(0) saturate(100%) invert(26%) sepia(98%) saturate(946%) hue-rotate(176deg) brightness(110%) contrast(113%) brightness(125%);
    }

    /* -- Sonderzins-/Ausland-Balken-Toggles: State-Text und Pfeil sind near-white
          -> auf der weissen Karte unlesbar. Text/Pfeil blau; gefuellte Balken
          (#DCEBF8, near-white) -> Blau, leere/dunkle Balken unveraendert. -- */
    #vergleich.kontrast-hell .vergleich-dashboard .balken-toggle-state { color: #003A66; }
    #vergleich.kontrast-hell .vergleich-dashboard .balken-toggle-arrow { color: #00528D; }
    #vergleich.kontrast-hell .vergleich-dashboard .balken-toggle[data-state="on"] .balken-toggle-bars-grow .balken-toggle-bar,
    #vergleich.kontrast-hell .vergleich-dashboard .balken-toggle[data-state="on"] .balken-toggle-bars-dash .balken-toggle-bar,
    #vergleich.kontrast-hell .vergleich-dashboard .balken-toggle[data-state="off"] .balken-toggle-bars-dash .balken-toggle-bar:nth-child(-n+8) { background: #0070C0; }

    /* -- Footer-CTA-Reihe / Empty-State (DE: keine Heatmap, kein tabelle-disclaimer;
          "keine Ergebnisse" = .tabelle-keine-ergebnisse). -- */
    #vergleich.kontrast-hell .vp-zelle.vp-footer { background: #F7F9FC; border-top-color: rgba(0,82,141,0.15); color: #003A66; }
    #vergleich.kontrast-hell .ab-zelle.ab-cta { border-top-color: rgba(0,82,141,0.15); }
    #vergleich.kontrast-hell .tabelle-keine-ergebnisse { color: #111; }
    #vergleich.kontrast-hell .vergleich-dashboard .footer-line a { color: #00528D; }
    #vergleich.kontrast-hell .vergleich-dashboard .footer-line a:hover { color: #0070C0; }

    /* -- CTA-Button "zum Anbieter": blaue Fuellung, weisse Schrift; Pfeil-Chip invertiert. -- */
    #vergleich.kontrast-hell .vergleich-dashboard .anbieter-link { background: #0070C0; color: #fff; }
    #vergleich.kontrast-hell .vergleich-dashboard .anbieter-link:hover { background: #00528D; }
    #vergleich.kontrast-hell .vergleich-dashboard .anbieter-link .link-arrow { background: #F7F9FC; color: #00528D; }

    /* -- Fussnoten (tabelle.min.css: hartkodiert Weiss-Text + Tuerkis-Links) -- */
    #vergleich.kontrast-hell .tabelle-fussnoten { background: rgba(0,82,141,0.05); color: #333; }
    #vergleich.kontrast-hell .tabelle-fussnoten li strong { color: #111; }
    #vergleich.kontrast-hell .tabelle-fussnoten a { color: #00528D; }
    #vergleich.kontrast-hell .tabelle-fussnoten a:hover { color: #0070C0; }

    /* -- Gruppen-Titel-Baender (Koernung) hell-blau statt Schwarz/Weiss-Transparenz -- */
    #vergleich.kontrast-hell .ab-gruppe-spacer, #vergleich.kontrast-hell button.vp-gruppentitel {
        background-color: rgba(0,82,141,0.06);
        background-image: radial-gradient(circle, rgba(0,82,141,0.10) 0 0.7px, transparent 1.1px);
        border-top-color: rgba(0,82,141,0.16); border-bottom-color: rgba(0,82,141,0.10);
        box-shadow: inset 0 1px 0 rgba(255,255,255,0.6);
    }
    #vergleich.kontrast-hell button.vp-gruppentitel { color: #00528D; }
    #vergleich.kontrast-hell .vp-gruppentitel-caret { color: #00528D; }
    #vergleich.kontrast-hell button.vp-gruppentitel:hover .vp-gruppentitel-caret,
    #vergleich.kontrast-hell button.vp-gruppentitel.is-row-hover .vp-gruppentitel-caret { color: #0070C0; }
    /* DE-eigen: Mobile-Gruppentitel-Caret-Hover (#BFDBEF) -> Blau. */
    #vergleich.kontrast-hell .tabelle-grid > .anbieter-spalte:first-child .mb-gruppentitel:hover .vp-gruppentitel-caret { color: #0070C0; }

    /* -- Einstellungsleiste: Anlagebetrag-Pills + Beschriftungen (aktive Pill nutzt
          background:var(--text-primary) -> im Hell-Modus #111; darum explizit blau/weiss). -- */
    #vergleich.kontrast-hell .vergleich-dashboard .laufzeit-nav { background: rgba(0,82,141,0.06); }
    #vergleich.kontrast-hell .vergleich-dashboard .laufzeit-pill { color: #003A66; }
    #vergleich.kontrast-hell .vergleich-dashboard .laufzeit-pill:hover { background: rgba(0,82,141,0.08); color: #003A66; }
    #vergleich.kontrast-hell .vergleich-dashboard .laufzeit-pill.active { background: #0070C0; color: #fff; }
    #vergleich.kontrast-hell .vergleich-dashboard .filter-label,
    #vergleich.kontrast-hell .vergleich-dashboard .filter-column-title { color: #003A66; }

    /* -- "weitere Filter"-Button (Floating): dunkelblau/tuerkis -> Weiss + Blau -- */
    #vergleich.kontrast-hell .anpassen-filter-btn { background: #F7F9FC; box-shadow: 0 0.125em 0.5em rgba(0,82,141,0.25); }
    #vergleich.kontrast-hell .anpassen-filter-btn:hover, #vergleich.kontrast-hell .anpassen-filter-btn.open { background: rgba(0,112,192,0.14); }
    #vergleich.kontrast-hell .anpassen-filter-btn:focus-visible { outline-color: #0070C0; }
    #vergleich.kontrast-hell .anpassen-filter-btn .ecke-tl { border-top-color: #0070C0; border-left-color: #0070C0; }
    #vergleich.kontrast-hell .anpassen-filter-btn .ecke-tr { border-top-color: #0070C0; border-right-color: #0070C0; }
    #vergleich.kontrast-hell .anpassen-filter-btn .ecke-bl { border-bottom-color: #0070C0; border-left-color: #0070C0; }
    #vergleich.kontrast-hell .anpassen-filter-btn .ecke-br { border-bottom-color: #0070C0; border-right-color: #0070C0; }
    #vergleich.kontrast-hell .anpassen-filter-btn .icon-wrap .icon-sliders { color: #00528D; }
    #vergleich.kontrast-hell .anpassen-badge { background: #0070C0; color: #fff; }

    /* -- Filter-Overlay-Panel: dunkelblau -> weisses Panel, blauer Rahmen; Backdrop bleibt -- */
    #vergleich.kontrast-hell .anpassen-panel {
        background: #F7F9FC; border-color: rgba(0,82,141,0.35);
        box-shadow: 0 0.5em 2.5em rgba(0,0,0,0.25), 0 0.125em 0.5em rgba(0,0,0,0.15);
    }
    #vergleich.kontrast-hell .filter-panel-titel { color: #00528D; border-bottom-color: rgba(0,82,141,0.18); }
    #vergleich.kontrast-hell .anpassen-panel .eingrenzungsfilter { border-top-color: rgba(0,82,141,0.12); }
    #vergleich.kontrast-hell .filter-checkbox { color: #333; }
    #vergleich.kontrast-hell .filter-checkbox:hover { color: #003A66; }
    #vergleich.kontrast-hell .vergleich-dashboard .filter-checkbox input[type="checkbox"] { border-color: rgba(0,82,141,0.5); background: #F7F9FC; }
    #vergleich.kontrast-hell .vergleich-dashboard .filter-checkbox input[type="checkbox"]:hover { border-color: #0070C0; }
    #vergleich.kontrast-hell .vergleich-dashboard .filter-checkbox input[type="checkbox"]:checked { background: #0070C0; border-color: #0070C0; }
    #vergleich.kontrast-hell .filter-checkbox input[type="checkbox"]:focus-visible { outline-color: #0070C0; }
    #vergleich.kontrast-hell .panel-close-btn { background: rgba(0,82,141,0.10); color: #00528D; }
    #vergleich.kontrast-hell .panel-close-btn:hover, #vergleich.kontrast-hell .panel-close-btn:focus { background: rgba(0,82,141,0.18); color: #003A66; }

    /* -- Pager (Skala/Chevrons): Tuerkis -> Blau -- */
    #vergleich.kontrast-hell .tabelle-pager-range { color: #111; }
    #vergleich.kontrast-hell .tabelle-pager-bereich, #vergleich.kontrast-hell .tabelle-pager-bereich strong { color: #00528D; }
    #vergleich.kontrast-hell .tabelle-pager-rest { color: #333; }
    #vergleich.kontrast-hell .tabelle-pager-btn { color: #0070C0; }
    #vergleich.kontrast-hell .tabelle-pager-btn:not(:disabled):hover, #vergleich.kontrast-hell .tabelle-pager-btn:focus-visible { color: #00528D; }
    #vergleich.kontrast-hell .tabelle-pager-btn:focus-visible { outline-color: #0070C0; }
    #vergleich.kontrast-hell .tabelle-pager-track::before { background: repeating-linear-gradient(90deg, rgba(0,82,141,0.20) 0 1px, transparent 1px 11px), rgba(0,82,141,0.08); }
    #vergleich.kontrast-hell .tabelle-pager-track:focus-visible { outline-color: #0070C0; }
    #vergleich.kontrast-hell .tabelle-pager-fenster { background: rgba(0,112,192,0.18); border-color: #0070C0; }

    /* -- Scroll-Indikator / native Scrollbar / Scroll-Fade-Kanten: Weiss -> Blau -- */
    #vergleich.kontrast-hell .tabelle-scrollbar-indikator { background: rgba(0,82,141,0.10); }
    #vergleich.kontrast-hell .tabelle-scrollbar-thumb { background: rgba(0,82,141,0.55); }
    #vergleich.kontrast-hell .tabelle-scroller.is-dragging ~ .tabelle-scrollbar-indikator .tabelle-scrollbar-thumb { background: rgba(0,82,141,0.75); }
    #vergleich.kontrast-hell .tabelle-scroller { scrollbar-color: rgba(0,82,141,0.55) rgba(0,82,141,0.10); }
    #vergleich.kontrast-hell .tabelle-scroller::-webkit-scrollbar-track { background: rgba(0,82,141,0.10); }
    #vergleich.kontrast-hell .tabelle-scroller::-webkit-scrollbar-thumb { background: rgba(0,82,141,0.55); }
    #vergleich.kontrast-hell .tabelle-scroller::-webkit-scrollbar-thumb:hover { background: rgba(0,82,141,0.75); }
    #vergleich.kontrast-hell .tabelle-wrapper::after { background: linear-gradient(to right, transparent 0%, rgba(0,82,141,0.14) 100%); }
    #vergleich.kontrast-hell .tabelle-wrapper::before { background: linear-gradient(to left, transparent 0%, rgba(0,82,141,0.14) 100%); }

    /* -- Europakarte-Buehne (Laenderfilter): bewusste dunkle Marken-Ausnahme.
          Ebene-B-Variablen + generische Hell-Overrides (filter-label/-column-title)
          wuerden die hellen Karten-Beschriftungen darauf ins Dunkle kippen. Darum die
          Schrift-Variablen lokal auf die DE-Dunkelmodus-Werte (aus vergleich.min.css)
          zuruecksetzen und die Beschriftungen wieder aufhellen — direkt NACH der
          generischen filter-label-Hell-Regel (Quellreihenfolge, gleiche Spezifitaet).
          Land-/Marker-/Preset-/Spalten-/Mint-Farben bleiben unveraendert. -- */
    #vergleich.kontrast-hell .ek-sektion {
        --text-primary: #ffffff; --text-secondary: rgba(255,255,255,0.7); --text-muted: rgba(255,255,255,0.5);
        --accent: #A9F6DB; --accent-light: #DFFDF2;
    }
    #vergleich.kontrast-hell .ek-sektion .filter-label,
    #vergleich.kontrast-hell .ek-sektion .filter-column-title { color: rgba(255,255,255,0.85); }

    /* -- Mobile (<=38em): Merkmal-Trennkante + Mini-Label + Info-Icons. Karte-randlos
          + 50vw-box-shadow + mobile #hilfe .icon liegen ZENTRAL (vergleich.min.css). -- */
    @media (max-width: 38em) {
        #vergleich.kontrast-hell .ab-zelle.ab-merkmal { border-bottom-color: rgba(0,82,141,0.14); }
        #vergleich.kontrast-hell .ab-mini-label { color: #00528D; }
        #vergleich.kontrast-hell .ab-info-icon { color: #00528D; }
        #vergleich.kontrast-hell .ab-info-icon:hover, #vergleich.kontrast-hell .ab-info-icon:focus-visible { color: #003A66; }
        #vergleich.kontrast-hell .ab-info-icon.ab-info-icon-mini-label { color: #00528D; }
        #vergleich.kontrast-hell .ab-info-icon.ab-info-icon-mini-label:hover, #vergleich.kontrast-hell .ab-info-icon.ab-info-icon-mini-label:focus-visible { color: #003A66; }
    }
    /* === Ende Hochkontrast-Hell-Modus (Ebene C) === */

    /* Diagrammansicht-Glyphe (Zins-Skyline). Noch inert, weil das <li> gedrosselt ist —
       gehoert aber JETZT hierher: .icon traegt in style.css unscoped Fremd-Styles aus dem
       Zinschart-Einsatz (font-size:3em, position:absolute, margin-left:-1.6em). Ohne diesen
       Reset rendert das Inline-SVG mit Breite 0, der Eintrag waere nach dem Einschalten
       unsichtbar. Werte gespiegelt von Festgeld DE (diagramm-festgeld-core.inc.php). */
    /* position MUSS relative sein, nicht static: style.css vergroessert die
       Tap-Targets mit "a > .icon::after { position:absolute; inset:-5px }".
       Bei static faellt der Bezugsrahmen dieses ::after auf einen Vorfahren
       zurueck — die unsichtbare Trefferflaeche wird ~330px breit und verdeckt
       die Nachbar-Icons: oberhalb 72em sind Tabellen- und Listen-Icon dann
       nicht mehr klickbar, ohne dass man etwas sieht (live gemessen 18.07.2026
       auf AT und DE). relative behaelt die Position im Fluss und stellt den
       Bezugsrahmen wieder her. Beim Portieren nicht auf static zuruecksetzen. */
    #hilfe .zg-view-icon { display: block; position: relative; margin: 0 auto; width: 1.3em; line-height: 1; font-size: 1.85em; }
    #hilfe .zg-view-icon svg { width: 1.3em; height: 0.91em; vertical-align: -0.08em; display: inline-block; }
    @media only screen and (max-width: 88em) {
        #hilfe .zg-view-icon { font-size: 1.3em; }
    }
    @media only screen and (max-width: 72em) {
        #hilfe .zg-view-icon { font-size: 1.2em; position: relative; margin: 0; }
    }

    /* Absatzwechsel innerhalb einer Fussnote (siehe .fn-absatz im PHP-Block):
       definierter Abstandshalter statt der vollen Leerzeile aus <br><br>.
       0.35em ergibt gemessene 7,4 px — unterhalb der 8,8 px zwischen zwei
       Anbieter-Eintraegen, damit die Absaetze sichtbar zum selben Eintrag
       gehoeren. Herkunft der Messreihe: fussnoten-absatzabstand-rollout-
       uebergabe.md (Tabellendarstellung/Festgeld DE). */
    .tabelle-fussnoten .fn-absatz { display: block; height: 0.35em; }

    /* === Icon-Zeile 2026-08-19 (DE-Rollout Phase 3) ===
       Kontrast-Toggle + "weitere Filter" in EINER Zeile, buendig unter den
       #hilfe-Glyphen (Bezug ist die Glyph-MITTE, nicht die Kante). Die
       Toggle-Basis liegt zentral in vergleich.min.css; hier steht nur der
       Override per #vergleich-Praefix - die min.css bleibt unveraendert,
       weil sie fuer alle Produkte des Markts gilt.
       ZWEI Desktop-Baender: DE hat bei 88em eine Glyphen-Stufe, die die
       Icon-MITTEN verschiebt (AT hat sie nicht). Konstanten live kalibriert
       (Icon-Gruppe A, 4 Icons), Restfehler < 0,04px ueber
       1200/1366/1400/1408/1420/1500/1920. */
    #vergleich .kontrast-zeile {
        display: block; position: relative;
        height: 0; margin: 0; overflow: visible;
        z-index: 1;
    }
    #vergleich .kontrast-toggle {
        position: absolute; right: calc(0.403% + 1.439em); top: 0.98em;
        width: 2.51em; height: 2.09em; padding: 0;
        display: inline-flex; align-items: center; justify-content: center;
        font-size: 0.85rem; font-weight: 600; line-height: 1.2;
        letter-spacing: 0.02em; color: #e8f2fb;
        background: rgba(9,87,143,0.62); box-shadow: 0 0.125em 0.5em rgba(0,0,0,0.25);
        border: 0; border-radius: 0; cursor: pointer;
        white-space: nowrap; -webkit-tap-highlight-color: transparent;
        transition: background 150ms ease, color 150ms ease;
    }
    #vergleich .vergleich-dashboard { position: relative; }
    #vergleich .anpassen-filter-btn {
        bottom: auto; top: calc(0.98em - var(--space-md)); right: calc(7.225em - 0.612%);
        width: 2.51em; height: 2.09em; font-size: 0.85rem;
    }
    #vergleich .anpassen-filter-btn .icon-wrap .icon-sliders { font-size: 1.05em; }
    #vergleich .anpassen-filter-btn .ecke { width: 0.7em; height: 0.7em; }
    #vergleich .anpassen-filter-btn .ecke-tl { top: 0.22em; left: 0.22em; }
    #vergleich .anpassen-filter-btn .ecke-tr { top: 0.22em; right: 0.22em; }
    #vergleich .anpassen-filter-btn .ecke-bl { bottom: 0.22em; left: 0.22em; }
    #vergleich .anpassen-filter-btn .ecke-br { bottom: 0.22em; right: 0.22em; }
    @media (max-width: 88em) {
        #vergleich .kontrast-toggle { right: calc(0.403% + 1.100em); }
        #vergleich .anpassen-filter-btn { right: calc(6.035em - 0.609%); }
    }
    @media (max-width: 72em) {
        #vergleich .kontrast-toggle { top: 0.97em; right: 0.85em; }
        #vergleich .anpassen-filter-btn { top: calc(0.97em - var(--space-md)); right: 3.92em; }
    }
    @media (max-width: 38em) {
        #vergleich .kontrast-toggle { top: 0.4em; right: 0.6em; }
        #vergleich .anpassen-filter-btn { top: calc(0.4em - var(--space-sm)); right: 4.13em; }
        #vergleich .vergleich-dashboard { padding-top: calc(var(--space-sm) + 0.5rem); }
    }
    /* === Ende Icon-Zeile === */
