/* Zentraler Content-Container, der Header, Hauptbereich und Footer in
   gleicher Breite ausrichtet. Header-/Footer-Hintergrund läuft full-width,
   nur der Inhalt wird auf max. 1280 px begrenzt und zentriert. So sitzen
   Logo-Kante, Login-Button und Content-Card bündig untereinander. */
.app-container {
    width: 100%;
    max-width: 1280px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 1rem;
    padding-right: 1rem;
}

/* === Hersteller-Gitter: A–Z Buchstaben-Leiste ========================
   Volle Breite, Buchstaben strecken sich gleichmäßig (flex:1) und brechen
   auf schmalen Viewports um. Aktiver Buchstabe = Primary; Buchstaben ohne
   Treffer (.is-empty) ausgegraut. .ds-letter-hidden blendet gefilterte
   Karten aus (kombiniert mit d-none der Suche → UND-Logik). */
.brand-alphabet {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin-bottom: 1.25rem;
}
.brand-alphabet-btn {
    flex: 1 1 auto;
    min-width: 2rem;
    padding: .35rem .25rem;
    border: 1px solid #dee2e6;
    background: #fff;
    border-radius: .375rem;
    font-size: .85rem;
    font-weight: 600;
    line-height: 1.2;
    color: #495057;
    cursor: pointer;
    transition: background-color .12s, border-color .12s, color .12s;
}
.brand-alphabet-btn:hover:not(.is-empty) { background: #f1f3f5; }
.brand-alphabet-btn.active {
    background: var(--bs-primary, #0d6efd);
    border-color: var(--bs-primary, #0d6efd);
    color: #fff;
}
.brand-alphabet-btn.is-empty {
    opacity: .4;
    cursor: default;
    color: #adb5bd;
}
[data-brand-item].ds-letter-hidden { display: none !important; }

/* Quill-Alignment-Klassen: der Rich-Text-Editor (Quill snow) markiert ausgerichtete
   Absätze über CSS-Klassen statt inline-Style. Im Frontend ist Quill's CSS nicht
   geladen, deshalb müssen wir die Klassen explizit aufnehmen, sonst bleibt alles
   links-bündig. */
.ql-align-center  { text-align: center; }
.ql-align-right   { text-align: right; }
.ql-align-justify { text-align: justify; }

/* „Rahmen"-Klasse aus dem Editor (Frame-Toggle aus dem +-Menü) — ein einziges
   <div class="ds-content-frame">, das via Quill-Container-Blot mehrere <p>-
   Zeilen umschließt. Bootstrap-card-artiger Look. */
.ds-content-frame {
    background: #f8f9fa;
    border: 1px solid #dee2e6;
    border-radius: .375rem;
    padding: 1rem 1.25rem;
    margin: 1rem 0;
}
.ds-content-frame > :last-child { margin-bottom: 0; }
.ds-content-frame > :first-child { margin-top: 0; }

/* Textbereich-Inhalte: gleiches tight-paragraph-Verhalten wie im Quill-Editor.
   Bootstrap setzt sonst margin-bottom: 1rem auf jeden <p>, was Adress-/
   Kontaktblöcke (jede Zeile = ein <p>) mit großen Lücken auseinanderreißt.
   Bewusst gewollte Leerzeilen rendert Quill als <p><br></p> — das <br>
   nimmt weiterhin eine Zeilenhöhe ein und sorgt für die optische Trennung
   zwischen Blöcken (z. B. zwischen „Firmensitz" und „Telefon"). */
.textbereich-module p { margin: 0; padding: 0; }
/* Listen behalten ihre Default-Margins; bei Überschriften reicht ein
   etwas dezenterer Abstand, damit sie sich visuell vom Folge-Text absetzen. */
.textbereich-module h1,
.textbereich-module h2,
.textbereich-module h3,
.textbereich-module h4 { margin-top: 1rem; margin-bottom: .5rem; }
/* In der Karte rahmt allein das symmetrische Padding den Inhalt: Der Aussen-
   abstand des ersten (oben) und letzten Elements (unten) entfaellt, sonst sitzt
   z. B. eine einzelne Ueberschrift sichtbar zu hoch in der Karte. */
.textbereich-module .card-body > :first-child { margin-top: 0; }
.textbereich-module .card-body > :last-child { margin-bottom: 0; }
.textbereich-module h1:first-child,
.textbereich-module h2:first-child,
.textbereich-module h3:first-child,
.textbereich-module h4:first-child { margin-top: 0; }
/* Direkt aufeinanderfolgende Überschriften (Titel + Untertitel) dicht halten —
   sonst schiebt das margin-top des zweiten Headings es im Frontend zu weit vom
   ersten weg (im Quill-Editor stehen die Zeilen enger). */
.textbereich-module :is(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6) { margin-top: 0; }

.hover-shadow:hover {
    box-shadow: 0 .25rem .5rem rgba(0,0,0,.1);
    border-color: #0d6efd !important;
}

/* === Kategorie-Slider ============================================
   Horizontaler Scroll-Snap-Track ohne Zusatz-Library. Anzahl sichtbarer
   Karten am Desktop über --slider-cols (vom Modul gesetzt). Mobil/Tablet
   feste Stufen, damit immer ein „Peek" der nächsten Karte sichtbar ist. */
.category-slider-track {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;        /* Firefox: Scrollbar ausblenden */
    -ms-overflow-style: none;
    /* overflow-x:auto klippt auch vertikal → oben/unten Platz lassen, damit der
       Karten-Schatten und die abgerundeten Ecken (auch beim Hover-Lift) nicht
       abgeschnitten werden ("outlines oben"). Horizontal 0, damit das Einrasten
       auf die Boxkanten exakt trifft (linke Box immer voll sichtbar). */
    padding: .5rem 0 1rem;
    /* Randspur für die Pfeile links/rechts (wie refixo) — Pfeile überlappen
       so nicht mehr die Karten, sondern sitzen daneben. */
    margin: 0 44px;
}
.category-slider-track::-webkit-scrollbar { display: none; }
.category-slider-item {
    scroll-snap-align: start;
    flex: 0 0 auto;
    /* mobil: ~2 Karten sichtbar */
    width: calc((100% - 1rem) / 2);
}
@media (min-width: 768px) {
    /* Tablet: ~3 Karten */
    .category-slider-item { width: calc((100% - 2rem) / 3); }
}
@media (min-width: 992px) {
    /* Desktop: nach Admin-Wahl (var). N Karten → (N-1) Lücken à 1rem. */
    .category-slider-item {
        width: calc((100% - (var(--slider-cols, 5) - 1) * 1rem) / var(--slider-cols, 5));
    }
}

.category-slider-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid #dee2e6;
    background: #fff;
    color: #212529;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(0,0,0,.1);
    cursor: pointer;
    transition: background .2s ease, color .2s ease, border-color .2s ease, opacity .2s ease;
}
.category-slider-nav:hover { background: var(--bs-primary, #0d6efd); color: #fff; border-color: var(--bs-primary, #0d6efd); }
/* Pfeile in der Randspur (0 statt -8px) — sitzen neben dem Track, nicht über den Karten. */
.category-slider-prev { left: 0; }
.category-slider-next { right: 0; }
.category-slider-nav:disabled { opacity: .35; pointer-events: none; }

@media (max-width: 575px) {
    /* Schmalere Randspur auf dem Handy (wie refixo). */
    .category-slider-track { margin: 0 36px; }
}

/* Kategorie-Karten im Slider — Optik wie refixo.de (abgerundet, Hover-Lift, Primär-CTA).
   Sichtbare Umrandung (auch oben), da der Slider-Abschnitt keinen grauen Hintergrund
   hat und der reine shadow-sm auf Weiß kaum erkennbar ist. Höhere Spezifität
   (.category-slider-item …) schlägt Bootstraps .border-0 !important.

   Die Modell-Kacheln (/reparatur/{kat}/{hersteller}) und die Hersteller-Kacheln
   (/reparatur/{kat}) teilen sich dieselben Regeln: gleiche Optik, eine Quelle.
   Deshalb überall gruppierte Selektoren statt kopierter Regelblöcke — sonst
   laufen die Ansichten auseinander, sobald an einer geschraubt wird. */
.category-slider-item .cat-slider-card,
.brand-grid-module .brand-card,
.model-grid-module .model-card {
    border: 1px solid #e5e7eb !important;
    border-radius: .75rem !important;
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.category-slider-item .cat-slider-card:hover,
.brand-grid-module .brand-card:hover,
.model-grid-module .model-card:hover {
    border-color: var(--bs-primary, #0d6efd) !important;
    transform: translateY(-4px);
    box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.12) !important;
}
/* Quadratische Karten. Vorher gab eine feste Bildhöhe die Höhe vor — zusammen
   mit dem py-4 des card-body wurde die Karte höher als breit (Hochformat) und
   um den Schriftzug stand auffällig viel Leerraum. Jetzt bestimmt die
   Kartenbreite die Höhe, und das Bild füllt, was der Schriftzug übrig lässt.
   Das gilt bei jeder Spaltenzahl, ohne dass ein Pixelwert nachgezogen werden muss. */
.category-slider-item .cat-slider-card,
.brand-grid-module .brand-card,
.model-grid-module .model-card { aspect-ratio: 1; }
.category-slider-item .cat-slider-body {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    /* schlanker als Bootstraps card-body-Default — das war der „dicke Rand"
       ober- und unterhalb des Schriftzugs. */
    padding: .75rem;
    min-height: 0;   /* sonst schrumpft das Bild im Flex-Container nicht mit */
}
/* Bild nimmt die Restfläche über dem Schriftzug; contain wahrt das
   Seitenverhältnis, egal wie die Kategorie-Bilder zugeschnitten sind. */
.category-slider-item .cat-slider-img {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    object-fit: contain;
}
/* Kategoriename + Pfeil als reiner Schriftzug (kein Button mehr). Er ist
   zugleich der Titel der Karte — die separate Überschrift entfiel, als der
   Name aus dem CTA hierher wanderte. Namen wie „Navigationssystem" sind
   breiter als eine Karte bei 5 Spalten, deshalb umbrechen lassen. */
.category-slider-item .cat-slider-label {
    flex: 0 0 auto;
    display: block;
    font-weight: 600;
    line-height: 1.3;
    overflow-wrap: anywhere;
    transition: color .2s ease;
}
/* Die ganze Karte ist der Link — Farbwechsel deshalb am Karten-Hover, nicht
   am Schriftzug selbst (der fängt den Zeiger nur auf einem Teil der Fläche). */
.category-slider-item .cat-slider-card:hover .cat-slider-label,
.brand-grid-module .brand-card:hover .brand-card-label,
.model-grid-module .model-card:hover .model-card-label {
    color: var(--bs-primary, #0d6efd);
}
/* Fallback-Icon (API liefert kein Bild) sitzt in derselben Restfläche wie das
   Bild. Eine font-size kann nicht mitschrumpfen wie ein Bild, daher fester Wert
   und zentriert — bei quadratischer Karte bleibt darum herum genug Platz. */
.category-slider-item .cat-slider-icon {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3.5rem;
    line-height: 1;
}

/* === Modell- und Hersteller-Kacheln: Name als Overlay im Bild ============
   Anders als im Slider steht der Name NICHT unter dem Bild, sondern liegt
   unten darüber. Grund: aspect-ratio gibt die Höhe nur VOR — steht der Name
   im Fluss und bricht um („Mavic 3 T Enterprise Thermal Camera", 35 Zeichen),
   wächst die Kachel darüber hinaus und die Zeile bekommt ungleiche Höhen.
   Als Overlay ist der Name aus dem Fluss genommen und kann die Kachel
   grundsätzlich nicht mehr aufblähen — das Quadrat hält immer, und das Bild
   bekommt die volle Fläche statt sie mit einer Textzeile zu teilen.
   overflow:hidden nimmt zusätzlich die automatische Mindesthöhe. */
.brand-grid-module .brand-card,
.model-grid-module .model-card {
    overflow: hidden;
    position: relative;
}
/* Bild füllt das GANZE Quadrat — auch den Streifen, auf dem der Name liegt.
   Vorher blieb unten 2.1rem frei, damit der Name das Gerät nicht berührt; das
   Motiv stand dadurch aber immer oberhalb des Schriftzugs und der Name wirkte
   „unter dem Bild" statt darauf. Jetzt liegt er wirklich darüber, und das
   Motiv bekommt die volle Kantenlänge. Absolut positioniert statt im Fluss:
   der card-body entfällt damit, und die Höhe kommt allein aus aspect-ratio. */
.brand-grid-module .brand-card-img,
.brand-grid-module .brand-card-icon,
.model-grid-module .model-card-img,
.model-grid-module .model-card-icon {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: .5rem;
    object-fit: contain;   /* wahrt das Seitenverhältnis */
}
/* Fallback-Icon (die meisten Modelle haben kein Bild): eine Schriftgröße
   skaliert nicht wie ein Bild, daher fester Wert und mittig in derselben Fläche.
   Anders als beim Bild bleibt unten Platz: ein Glyph hinter dem Schriftzug wäre
   nur noch ein Fleck, während ein Foto dort weiterläuft und trägt. */
.brand-grid-module .brand-card-icon,
.model-grid-module .model-card-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    padding-bottom: 2.1rem;
    font-size: 3rem;
    line-height: 1;
}
.brand-grid-module .brand-card-label,
.model-grid-module .model-card-label {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 1.4rem .5rem .45rem;
    /* Verlauf statt Balken: auf freigestellten Bildern (weißer Grund) fällt er
       nicht auf, auf dunklen Motiven trägt er den Text trotzdem. */
    background: linear-gradient(to top, rgba(255,255,255,.97) 55%, rgba(255,255,255,0));
    font-size: .9375rem;   /* 15px statt 13px — auf der Kachel war es zu zierlich */
    font-weight: 600;
    line-height: 1.25;
    /* Zwei Zeilen, dann „…" — der volle Name steht im title-Attribut. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    /* anywhere würde mitten im Wort trennen; bei Typenbezeichnungen wie
       „RS 2 Pro Combo" liest sich der Umbruch an der Lücke besser. */
    overflow-wrap: normal;
}
/* „Grafiken anzeigen" im Modul abgeschaltet: dann fällt auch das Quadrat weg —
   eine leere quadratische Fläche mit einem Wort in der Mitte wäre nur viel
   Nichts. Stattdessen bestimmt der Name selbst die Höhe, die Kacheln werden zu
   kompakten Schaltflächen. Der Verlauf entfällt, er hat ohne Bild keinen Zweck;
   die Zeilenkürzung ebenso — Hersteller- und Modellnamen dürfen hier umbrechen. */
.brand-grid-module .brand-card.is-textonly,
.model-grid-module .model-card.is-textonly { aspect-ratio: auto; }
.brand-grid-module .brand-card.is-textonly .brand-card-label,
.model-grid-module .model-card.is-textonly .model-card-label {
    position: static;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 3.75rem;
    padding: .9rem .75rem;
    background: none;
}

#searchResults {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1050;
    max-height: 320px;
    overflow-y: auto;
}

#searchResults .dropdown-item {
    white-space: normal;
}

/* Suchergebnisse: kompakte Zeilen, einheitliche Schrift (keine Hervorhebung) */
#searchResults .search-result-item {
    padding-top: .3rem;
    padding-bottom: .3rem;
    font-size: .875rem;
    font-weight: 400;
    line-height: 1.3;
}

#searchResults .search-result-item .search-sep {
    color: #adb5bd;
    margin: 0 .15rem;
}

/* === Filter-Leiste (filter_bar) ===================================== */
/* Layout angelehnt an die Essays-Filterleiste: Suchfeld mit innenliegendem
   Icon + Such-Button, daneben das Kategorie-Listenfeld. Light-Theme-Variante.
   Optional beim Scrollen oben fixiert (is-sticky). */
.filter-bar-module.is-sticky {
    position: sticky;
    top: 0;
    z-index: 1020;
    background: #fff;
    box-shadow: 0 1px 0 rgba(0, 0, 0, .08);
}

.filter-bar-module .ds-filter-row {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    flex-wrap: nowrap;
}

/* Such-Gruppe (Feld + Button) nimmt den freien Platz ein */
.filter-bar-module .ds-filter-search-group {
    display: flex;
    align-items: center;
    gap: 8px;
}
/* Suchfeld-Spalte wächst (volle Breite), Kategorie-Spalte bleibt schmal rechts */
.filter-bar-module .ds-filter-half { flex: 1 1 0; min-width: 0; }
.filter-bar-module .ds-filter-cat-col { flex: 0 0 auto; min-width: 0; }

.filter-bar-module .ds-filter-search {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
}
.filter-bar-module .ds-filter-search-icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: #8a8a8a;
    pointer-events: none;
    font-size: .95rem;
}
.filter-bar-module .ds-filter-search-input { padding-left: 34px; }
.filter-bar-module .ds-filter-search-btn { flex: 0 0 auto; }

/* === Suchfeld im Modell-Gitter ======================================
   Feld und Knopf sitzen hier in EINEM gerahmten Kasten mit runden Ecken,
   nicht als zwei getrennte Elemente nebeneinander. Bewusst nur auf
   .model-grid-search gemuenzt — die Filter-Leisten der Kategorie- und
   Modell-Seiten behalten ihr bisheriges Aussehen. */
.model-grid-search .ds-filter-search-group {
    border: 1px solid #d7dce3;
    border-radius: .75rem;
    background: #fff;
    padding: .25rem;
    gap: .25rem;
}
/* Das Feld bringt seinen eigenen Rahmen mit — der wuerde im Kasten doppelt
   wirken. Auch der Fokus-Ring wandert nach aussen an den Kasten. */
.model-grid-search .ds-filter-search-input {
    border: 0;
    background: transparent;
    box-shadow: none;
}
.model-grid-search .ds-filter-search-input:focus { box-shadow: none; }
.model-grid-search .ds-filter-search-btn { border-radius: .5rem; }
.model-grid-search .ds-filter-search-group:focus-within {
    border-color: var(--bs-primary, #0d6efd);
    box-shadow: 0 0 0 .2rem rgba(var(--bs-primary-rgb, 13, 110, 253), .15);
}

/* Kategorie-Listenfeld rechts, feste Mindestbreite (wie die Referenz) */
.filter-bar-module .ds-filter-category {
    flex: 0 0 auto;
    min-width: 200px;
    width: auto;
}

/* Mobil (< 768 px): Suchleiste volle Breite, Listenfeld darunter volle Breite */
@media (max-width: 767.98px) {
    .filter-bar-module .ds-filter-row { flex-wrap: wrap; }
    .filter-bar-module .ds-filter-half { flex: 1 1 100%; }
    .filter-bar-module .ds-filter-cat-col { flex: 1 1 100%; }
    .filter-bar-module .ds-filter-search-group { flex: 1 1 100%; }
    .filter-bar-module .ds-filter-category { flex: 1 1 100%; min-width: 0; }
}

/* === model_filter_bar: Felder mit optionalen Labels (Spalten) ======== */
/* Jede Spalte = optionaler <small>-Text über dem Feld; Felder unten bündig. */
.filter-bar-module .ds-mfb-row {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    flex-wrap: nowrap;
}
.filter-bar-module .ds-mfb-col {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex: 0 0 auto;
}
.filter-bar-module .ds-mfb-col-search { flex: 1 1 0; min-width: 0; }
.filter-bar-module .ds-mfb-sublabel { line-height: 1.2; }
@media (max-width: 767.98px) {
    .filter-bar-module .ds-mfb-row { flex-wrap: wrap; }
    .filter-bar-module .ds-mfb-col { flex: 1 1 100%; }
}

/* === „Modell nicht gefunden"-Box (model_filter_bar) ================== */
/* Jumbotron-artige Call-out-Box, die app.js bei 0 Suchtreffern einblendet. */
.filter-bar-module .model-notfound {
    margin-top: 1rem;
    padding: 2.5rem 1.5rem;
    background: #f8f9fa;
    border: 1px solid #e9ecef;
    border-radius: 1rem;
}
.filter-bar-module .model-notfound-icon {
    display: block;
    font-size: 3rem;
    line-height: 1;
    color: #0d6efd;
}
.filter-bar-module .model-notfound-text {
    max-width: 540px;
    margin-left: auto;
    margin-right: auto;
}

/* === Footer-Spalten (Frontend) ===================================== */
.footer-module .footer-cols-divider { border-color: rgba(255, 255, 255, .15); opacity: 1; }
.footer-module .footer-col-link:hover { color: #fff !important; }

/* Footer-Spaltentitel: Rich-Text (Quill). KEINE automatische Schriftstärke,
   -größe oder Farbe — alles kommt ausschließlich aus dem Editor. Nur die
   Default-Block-Margins (Quills <p>/Headings) werden geglättet (strukturell). */
.footer-module .footer-col-title p { margin: 0; }
.footer-module .footer-col-title :is(h1, h2, h3, h4, h5, h6) { margin: 0; }

/* === Footer-Spalten: EXAKT gleicher Zeilenabstand überall ============
   Egal ob <p>, <ul>/<ol> oder <li> — jede Zeile im Footer-Spaltenbereich nutzt
   dieselbe line-height und hat keine Block-Margins/Paddings. !important, um
   Bootstrap-Defaults (p-Margin, li-Listendarstellung) sicher zu überschreiben.
   Hinweis: nur p/ul/ol/li werden zurückgesetzt — NICHT die Spalten-<div>s, damit
   die Bootstrap-Gutter (Spaltenabstände) erhalten bleiben. */
.footer-module .footer-cols,
.footer-module .footer-cols * { line-height: 1.5 !important; }
.footer-module .footer-cols p,
.footer-module .footer-cols ul,
.footer-module .footer-cols ol,
.footer-module .footer-cols li {
    margin: 0 !important;
    padding: 0 !important;
}
.footer-module .footer-cols ul,
.footer-module .footer-cols ol { list-style: none !important; }
.footer-module .footer-cols li { display: block !important; }

/* === Footer: Zahlungsarten-Leiste ==================================== */
/* Monochrom, gedämpftes Grau wie der übrige Footer; dünne Trennlinie oben;
   horizontale Reihe, auf Mobile umbrechend (flex-wrap). */
.footer-module .footer-payments {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: flex-start;
    gap: 1.1rem 2rem;
    margin-top: 1rem;
    padding-top: 1rem;
    /* Eigene Trennlinie ÜBER der Leiste (zwischen Links und Zahlungsarten) —
       analog zur bestehenden HR. Darunter folgt die HR vor dem Copyright. */
    border-top: 1px solid rgba(255, 255, 255, .15);
}
.footer-module .footer-payment {
    display: flex;
    flex-direction: row;       /* Icon links, Text rechts daneben */
    align-items: center;       /* Icon und Text vertikal mittig zueinander */
    gap: .55rem;
    color: #adb5bd;            /* helles, gedämpftes Grau – kein Branding */
}
.footer-module .footer-payment i {
    font-size: 1.8rem;         /* einheitliche Icon-Größe */
    line-height: 1;
    flex: 0 0 auto;
    color: inherit;            /* monochrom: gleiche Grau-Farbe wie das Label */
}
.footer-module .footer-payment-label {
    display: flex;
    flex-direction: column;    /* Beschriftung + optionale Unterzeile gestapelt */
    justify-content: center;
    line-height: 1.15;
    font-size: .95rem;         /* größere, gut sichtbare Beschriftung */
    text-align: left;
}
.footer-module .footer-payment-sub {
    font-size: .72rem;         /* kleine Unterzeile (per Vorkasse / girocard) */
    opacity: .72;
}

/* === Login-Modul: vollflächiges Hintergrundbild + schwebende Card =====
   Das Bild bedeckt die GANZE Section (cover, volle Breite × Höhe). Darüber ein
   durchgehender dunkler Overlay/Verlauf. Die Login-Card schwebt rechts (vertikal
   mittig), die Feature-Punkte unten links. Füllt im Body-Flex-Column den freien
   Platz (flex: 1) → kein weißer Balken. */
.login-fullbg {
    position: relative;
    display: flex;
    align-items: center;          /* Card vertikal mittig */
    justify-content: flex-end;    /* Card rechts */
    flex: 1 0 auto;
    min-height: 480px;
    padding-left: 1.5rem;
    padding-right: clamp(1.5rem, 6vw, 6rem);
    background-color: #131a2a;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    color: #e8ecf3;
}
/* Durchgehender dunkler Overlay über das GESAMTE Bild (unter Card/Features) */
.login-overlay {
    position: absolute; inset: 0;
    background:
        linear-gradient(to top, rgba(8,12,22,.9) 0%, rgba(8,12,22,.3) 50%, rgba(8,12,22,.35) 100%),
        rgba(8,12,22,.25);
}
/* Feature-Band: volle Breite am Boden; der innere .app-container zentriert auf
   1280px und gibt das gleiche linke Padding wie der Footer → Feature-Spalte
   fluchtet linksbündig mit dem übrigen Seiteninhalt. */
.login-features {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
}
.login-features .app-container {
    padding-top: 2.75rem;
    padding-bottom: 3rem;
}
.login-features-col {
    display: flex; flex-direction: column; gap: 1.4rem;
    max-width: 460px;
}
.login-feature { display: flex; align-items: flex-start; gap: 1rem; }
.login-feature i { font-size: 1.5rem; line-height: 1; color: #fff; flex: 0 0 auto; margin-top: .15rem; }
.login-feature-title { font-weight: 700; color: #fff; }
.login-feature-sub { font-size: .9rem; color: rgba(255,255,255,.78); }

/* Card-Wrap: schwebendes Panel rechts, über dem Overlay (z-index) */
.login-card-wrap {
    position: relative; z-index: 2;
    width: 100%; max-width: 430px;
}
.login-card {
    width: 100%; max-width: 430px;
    background: #1a2233;
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 1.1rem;
    padding: 2.5rem;
    box-shadow: 0 20px 60px rgba(0,0,0,.35);
}
.login-heading { font-size: 1.8rem; font-weight: 700; color: #fff; margin: 0 0 .35rem; }
.login-sub { color: #97a2b6; margin: 0 0 1.6rem; }

.login-field { position: relative; margin-bottom: 1rem; }
.login-field-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: #8b93a7; font-size: 1.05rem; pointer-events: none; }
.login-input {
    width: 100%;
    background: #0e1320;
    border: 1px solid rgba(255,255,255,.12);
    border-radius: .6rem;
    color: #fff;
    padding: .7rem .9rem .7rem 2.6rem;
    font-size: .95rem;
}
.login-input.has-toggle { padding-right: 2.6rem; }
.login-input::placeholder { color: #6b7585; }
.login-input:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 .2rem rgba(59,130,246,.2); }
.login-pass-toggle {
    position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
    background: none; border: none; color: #8b93a7; padding: .25rem .45rem; cursor: pointer;
}
.login-pass-toggle:hover { color: #fff; }

.login-alert {
    background: rgba(220,53,69,.15); border: 1px solid rgba(220,53,69,.4);
    color: #f1aab0; border-radius: .5rem; padding: .5rem .75rem; font-size: .85rem; margin-bottom: 1rem;
}

.login-row {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    margin: .25rem 0 1.25rem; font-size: .9rem;
}
.login-remember { display: inline-flex; align-items: center; gap: .5rem; color: #b9c2d4; margin: 0; cursor: pointer; }
.login-remember input { accent-color: #3b82f6; width: 16px; height: 16px; }
.login-link { color: #3b82f6; text-decoration: none; }
.login-link:hover { color: #60a5fa; text-decoration: underline; }

.login-btn-primary {
    display: block; width: 100%;
    background: linear-gradient(135deg, #2563eb, #3b82f6);
    border: none; border-radius: .6rem; color: #fff; font-weight: 600;
    padding: .8rem 1rem; font-size: 1rem; cursor: pointer;
    transition: filter .15s ease, box-shadow .15s ease;
}
.login-btn-primary:hover { filter: brightness(1.08); box-shadow: 0 8px 24px rgba(37,99,235,.35); }

.login-divider { display: flex; align-items: center; gap: 1rem; margin: 1.4rem 0; color: #6b7585; font-size: .85rem; }
.login-divider::before, .login-divider::after { content: ''; flex: 1; height: 1px; background: rgba(255,255,255,.12); }

.login-social {
    display: flex; align-items: center; justify-content: center; gap: .6rem; width: 100%;
    background: #0e1320; border: 1px solid rgba(255,255,255,.14); border-radius: .6rem;
    color: #e8ecf3; text-decoration: none; padding: .7rem 1rem; font-weight: 500; margin-bottom: .75rem;
    transition: background .15s ease, border-color .15s ease;
}
.login-social:hover { background: #141b2b; color: #fff; border-color: rgba(255,255,255,.25); }
.login-social i { font-size: 1.1rem; }

.login-register { text-align: center; color: #97a2b6; margin: 1.4rem 0 0; font-size: .9rem; }

/* Responsive: Spalten untereinander, Bild oben (reduziert), Features ausgeblendet */
@media (max-width: 767.98px) {
    .login-fullbg { justify-content: center; padding-left: 1rem; padding-right: 1rem; }
    .login-features { display: none; }
    .login-card-wrap { max-width: 460px; }
    .login-card { padding: 1.75rem; }
}

/* === Leistungen-Karte: seitlich einfahrender Aktions-Button ===========
   Beim Hover gleitet rechts ein Button über die volle Kartenhöhe herein
   (Slide-in). Die Leiste ÜBERLAPPT den Text — der Inhalt bewegt sich NICHT.
   Damit der Preis dabei nie verdeckt wird, liegt das Preis-Badge per höherem
   z-index immer obenauf; der Plus-/Mülleimer-Button sitzt vertikal mittig in
   der Leiste (NICHT auf Höhe des Preises oben rechts). Blau + Plus = hinzufügen;
   bei ausgewähltem Artikel (.is-selected) Rot + Mülleimer = entfernen.
   Auf Touch-Geräten (kein Hover) ist der Button dauerhaft sichtbar; dort bekommt
   der Inhalt statischen Platz (kein dynamisches Springen → unkritisch). */
.service-card { position: relative; overflow: hidden; --sca-w: 56px; --sca-gap: 12px; }
.service-card-action {
    position: absolute; top: 0; right: 0; height: 100%;
    width: var(--sca-w); border: 0; padding: 0; z-index: 1;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: 1.3rem; line-height: 1;
    background: var(--bs-primary, #0d6efd);   /* blau = hinzufügen */
    transform: translateX(100%);              /* eingefahren */
    transition: transform .25s ease, background-color .15s ease;
    cursor: pointer;
}
/* Preis bleibt IMMER sichtbar: liegt über der Leiste (z-index) UND gleitet beim
   Hover um die Leistenbreite nach links aus der Leiste heraus (nur das Badge
   bewegt sich, der übrige Text bleibt stehen und wird überlappt). */
.service-card .card-body { position: relative; }
.service-card .card-body .badge { position: relative; z-index: 2; transition: transform .25s ease; }
/* Preis-Badges alle gleich breit (rechtsbündig untereinander): feste Mindest-
   breite + zentrierter Text; laengere Preise (4-stellig) duerfen wachsen. */
.service-card .card-body .badge { min-width: 5.75rem; text-align: center; flex-shrink: 0; margin-left: .75rem; }
/* Die Leiste erscheint NUR, wenn die Leistung angeklickt (= im Warenkorb) ist —
   KEIN Einblenden beim Hover. Im Warenkorb: grün + Warenkorb-Icon, dauerhaft
   offen; der Preis ist entsprechend nach links verschoben und bleibt sichtbar. */
.service-card.is-selected .service-card-action {
    transform: translateX(0);
    background: var(--bs-success, #198754);
}
.service-card.is-selected .card-body .badge {
    transform: translateX(calc(-1 * (var(--sca-w) + var(--sca-gap))));
}
.service-card-action:hover { filter: brightness(.93); }

/* ── Nummerierungs-Balken der Leistungskarten (service_grid: show_numbers) ──
   Schwarzer Streifen ueber die volle Kartenhoehe am linken (Standard) oder
   rechten Rand mit fortlaufender Nummer; der Karteninhalt rueckt um die
   Balkenbreite ein. Farben kommen als Custom Properties von der Karte
   (--scn-bg / --scn-color, Admin). Rechts liegt der Balken unter dem
   einfahrenden Aktions-Button (z-index), der ihn im Warenkorb-Zustand ueberdeckt. */
.service-card { --scn-w: 44px; }
.service-card.has-number.num-left  .card-body { padding-left:  calc(var(--scn-w) + 1rem); }
.service-card.has-number.num-right .card-body { padding-right: calc(var(--scn-w) + 1rem); }
.service-card-num {
    position: absolute; top: 0; bottom: 0; width: var(--scn-w);
    display: flex; align-items: center; justify-content: center;
    background: var(--scn-bg, #212529); color: var(--scn-color, #fff);
    font-weight: 700; font-size: 1.25rem; line-height: 1; z-index: 0;
    pointer-events: none;
}
.service-card.num-left  .service-card-num { left: 0; }
.service-card.num-right .service-card-num { right: 0; }

/* ── Leiste ueber der Leistungsliste (service_grid: show_list_bar) ─────
   Gleiche Optik wie der Kartenkopf „Zusammenfassung" rechts: Rahmen,
   Rundung, Innenabstand, halbfette Schrift; Farben aus dem Admin. */
.service-list-bar {
    padding: .5rem 1rem; font-weight: 600;
    border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0,0,0,.175));
    border-radius: var(--bs-card-border-radius, .375rem);
}

/* ── Gelbe Notiz unter der Kasse (service_grid: show_note) ─────────────
   Haftnotiz-Optik: gelbe Flaeche, leicht abgesetzte Kante, weicher Schatten,
   minimal gedreht. Farbe kommt als --note-bg von der Box (Admin). */
.service-note {
    position: relative; padding: .9rem 1rem 1rem;
    background: var(--note-bg, #fff7b3); color: #3b3300;
    border-radius: 4px; transform: rotate(-.6deg);
    box-shadow: 0 6px 14px rgba(0,0,0,.14), 0 1px 0 rgba(0,0,0,.05);
    font-size: .95rem; line-height: 1.45;
}
.service-note::before {
    /* „Klebestreifen" oben mittig */
    content: ""; position: absolute; top: -9px; left: 50%; width: 64px; height: 18px;
    transform: translateX(-50%) rotate(1.5deg);
    background: rgba(255,255,255,.55); border: 1px solid rgba(0,0,0,.06);
}
.service-note-title { font-weight: 700; margin-bottom: .25rem; display: flex; align-items: center; gap: .4rem; }
.service-note-title .bi { color: #b58900; }
/* zweite Notiz leicht gegenlaeufig gedreht, wirkt wie zwei einzelne Zettel */
.service-note-2 { transform: rotate(.5deg); }
.service-note-3 { transform: rotate(-.4deg); }

/* ── Navbar-Suchmaske ─────────────────────────────────────────────────
   Auf Desktop (≥lg) echt mittig über die volle Navbar-Breite positioniert,
   auf Mobil im normalen Fluss (im aufgeklappten Menü). Lupen-Icon liegt
   links im Feld; der Input bekommt entsprechend Innenabstand links. */
/* Logo-Bild vor dem Logo-Text (Header-Modul: brand_logo) */
.navbar-brand-logo { width: auto; max-height: 60px; object-fit: contain; display: inline-block; vertical-align: middle; }

/* === Header-Topbar (dünne Leiste über der Navigation) ============== */
/* display:flex + align-items:center, damit eine im Modul gesetzte
   min-height den Inhalt vertikal zentriert statt ihn oben kleben zu lassen.
   Der innere .app-container hat width:100% und behält seine auto-Margins. */
.header-topbar { font-size: .8rem; line-height: 1.2; padding: 4px 0; display: flex; align-items: center; }
.header-topbar-link { color: rgba(255,255,255,.85); text-decoration: none; white-space: nowrap; }
.header-topbar-link:hover { color: #fff; text-decoration: underline; }
.header-topbar-left { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Trennstriche zwischen den Rechtslinks: AGB | Impressum | Datenschutz */
.header-topbar-right.has-sep { gap: 0 !important; }
.header-topbar-right.has-sep .header-topbar-link + .header-topbar-link::before {
    content: "|"; color: rgba(255,255,255,.45); margin: 0 .6rem; text-decoration: none; display: inline-block;
}
@media (max-width: 575.98px) {
    .header-topbar { font-size: .72rem; padding: 3px 0; }
    .header-topbar-right { gap: .6rem !important; }
    /* Mobil: Telefon + E-Mail links untereinander (kein Abschneiden), die
       Rechtslinks rutschen bei Platzmangel in eine eigene Zeile darunter. */
    .header-topbar .app-container { flex-wrap: wrap; row-gap: 2px; }
    .header-topbar-left { display: flex; flex-direction: column; gap: 1px; overflow: visible; }
    .header-topbar-left .header-topbar-link.ms-3 { margin-left: 0 !important; }
    .header-topbar-right { flex-basis: 100%; justify-content: flex-end; flex-wrap: wrap; }
}

/* === Footer-Topbar (dünne blaue Leiste über dem Footer, analog Header) ===== */
/* display:flex + align-items:center wie bei der Header-Topbar, damit eine im
   Modul gesetzte min-height den Inhalt vertikal zentriert. */
.footer-topbar { font-size: .8rem; line-height: 1.2; padding: 4px 0; color: rgba(255,255,255,.9); display: flex; align-items: center; }
.footer-topbar-left { min-width: 0; }
/* Verlinkter Leistentext: weiß und ohne Unterstreichung, erst beim Hovern hervorgehoben. */
.footer-topbar-link { color: #fff; text-decoration: none; font-weight: 500; }
.footer-topbar-link:hover, .footer-topbar-link:focus { color: #fff; text-decoration: underline; }
@media (max-width: 575.98px) {
    .footer-topbar { font-size: .72rem; padding: 3px 0; }
}

.navbar-search { position: relative; max-width: 400px; width: 100%; }
@media (min-width: 992px) {
    .navbar-search { position: absolute; left: 50%; transform: translateX(-50%); }
    /* Mit Kategorie-Select davor: der Wrap ist das zentrierte Element,
       die Suche darin läuft wieder statisch mit (nicht mehr absolut). */
    .navbar-search-wrap { position: absolute; left: 50%; transform: translateX(-50%); width: min(600px, 62vw); }
    .navbar-search-wrap .navbar-search { position: relative; left: auto; transform: none; max-width: none; }
}
.navbar-search-icon {
    position: absolute;
    left: .75rem; top: 50%;
    transform: translateY(-50%);
    color: #6c757d;
    pointer-events: none;
    z-index: 5;
}
.navbar-search input { padding-left: 2.1rem; }

/* === Breadcrumb-Modul =============================================== */
/* Eigener Stacking-Context, damit die Links anklickbar bleiben, falls ein
   nachfolgendes Modul (z. B. Checkout) mit einem .row-Gutter-Negativrand
   (margin-top:-1.5rem bei .g-4) nach oben über den Breadcrumb ragt und sonst
   dessen Klickfläche abfangen würde. */
.breadcrumb-module {
    position: relative;
    z-index: 1;
}

/* === SEO-Text „weiterlesen" (erste N Zeilen, Rest aufklappbar) ===== */
.seo-readmore .seo-readmore-body {
    display: -webkit-box;
    -webkit-line-clamp: var(--rm-lines, 5);
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.seo-readmore.is-open .seo-readmore-body {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
}
.seo-readmore-toggle { margin-top: .4rem; text-decoration: none; font-weight: 600; }
.seo-readmore-toggle:hover { text-decoration: underline; }

/* === Repaired-Devices: „Mehr erfahren"-Reiter ======================== */
/* Kleiner Tab, der oben aus der Section herauswächst und in das Modul
   darüber ragt (auf der Startseite in den Hero). translateY(-100%) setzt ihn
   komplett über die Kante, sodass seine Unterkante bündig mit der Section
   abschließt — er wirkt dadurch wie ein herausgezogener Zipfel derselben
   Fläche, nicht wie ein aufgelegter Button. */
.repaired-devices-module.has-more-tab {
    position: relative;
}
.repaired-devices-more-tab {
    position: absolute;
    top: 0;
    transform: translateY(-100%);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    padding: .5rem 1.1rem;
    border-radius: .6rem .6rem 0 0;
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    box-shadow: 0 -2px 6px rgba(0, 0, 0, .12);
    transition: filter .15s ease, padding-bottom .15s ease;
}
/* Links/rechts fluchten mit dem Seiteninhalt: .app-container ist 1280px breit
   und hat 1rem Innenabstand, die Inhaltskante liegt also bei 50% - 640px + 1rem.
   Unterhalb von 1280px Viewport greift das max() und hält 1rem Randabstand. */
.repaired-devices-more-tab.is-center { left: 50%; transform: translate(-50%, -100%); }
.repaired-devices-more-tab.is-left   { left:  max(1rem, calc(50% - 640px + 1rem)); }
.repaired-devices-more-tab.is-right  { right: max(1rem, calc(50% - 640px + 1rem)); }

/* Mehrere Reiter nebeneinander: der Traeger uebernimmt Position und Ecke, die
   Reiter darin stehen im Fluss. Die Einzel-Regeln oben bleiben gueltig, damit
   aelteres Markup mit genau einem Reiter unveraendert funktioniert. */
.repaired-devices-more-tabs {
    position: absolute;
    top: 0;
    transform: translateY(-100%);
    z-index: 2;
    display: flex;
    align-items: flex-end;
    gap: .35rem;
    max-width: calc(100% - 2rem);
    flex-wrap: wrap;
}
.repaired-devices-more-tabs.is-center { left: 50%; transform: translate(-50%, -100%); }
.repaired-devices-more-tabs.is-left   { left:  max(1rem, calc(50% - 640px + 1rem)); }
.repaired-devices-more-tabs.is-right  { right: max(1rem, calc(50% - 640px + 1rem)); }
.repaired-devices-more-tabs .repaired-devices-more-tab {
    position: static;
    transform: none;
    left: auto;
    right: auto;
}

.repaired-devices-more-tab:hover,
.repaired-devices-more-tab:focus-visible {
    filter: brightness(1.06);
    padding-bottom: .7rem;      /* fährt minimal weiter heraus */
    text-decoration: none;
}
.repaired-devices-more-tab i {
    font-size: .85em;
    transition: transform .15s ease;
}
.repaired-devices-more-tab:hover i { transform: translateX(2px); }

@media (max-width: 575.98px) {
    .repaired-devices-more-tab {
        font-size: .875rem;
        padding: .4rem .85rem;
    }
}

/* === Schritte-/Ablauf-Modul ========================================= */
/* Eine umrandete Karte je Zeile: Grafik links, Text mittig, Grafik rechts.
   Die Flächen hinter den Grafiken behalten ihr Seitenverhältnis und halten
   die Zeilenhöhe stabil, auch solange noch kein Bild hinterlegt ist. */
.steps-row {
    padding: 1.25rem 1.4rem;
}
/* Das Bild füllt die Kachel randlos, damit die abgerundeten Ecken des
   Containers es auch wirklich beschneiden. Mit Innenabstand schwebte ein
   randvolles Motiv in der Kachel und zeigte seine EIGENEN, eckigen Ecken —
   sichtbar immer dann, wenn Bildhintergrund und Kachel-Tönung nicht zufällig
   dieselbe Farbe haben. */
.steps-media {
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    overflow: hidden;
    padding: 0;
}
.steps-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
/* Variante für freigestellte Motive (transparente PNG/SVG-Icons): Bild wird
   vollständig gezeigt, die getönte Fläche bleibt als Rahmen sichtbar. */
.steps-media.is-contain {
    padding: .6rem;
}
.steps-media.is-contain img {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
}
.steps-media-sm { aspect-ratio: 1 / 1; }
.steps-media-lg { aspect-ratio: 16 / 10; }
/* Admin-waehlbares Bildformat je Grafikspalte — ueberschreibt die Defaults oben
   (zwei Klassen schlagen die eine Default-Klasse in der Spezifitaet). */
.steps-media.is-1x1   { aspect-ratio: 1 / 1; }
.steps-media.is-4x3   { aspect-ratio: 4 / 3; }
.steps-media.is-16x9  { aspect-ratio: 16 / 9; }
.steps-media.is-16x10 { aspect-ratio: 16 / 10; }

.steps-heading {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.25;
    margin: 0 0 .55rem;
}
/* Kurzer Akzentstrich unter der Überschrift. */
.steps-rule {
    display: block;
    width: 46px;
    height: 4px;
    border-radius: 2px;
    margin-bottom: .8rem;
}
.steps-body {
    color: #55606d;
    line-height: 1.6;
}
.steps-body p:last-child { margin-bottom: 0; }

/* Unterzeile in Akzentfarbe zwischen Überschrift und Akzentstrich. */
.steps-subline {
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.3;
    margin: -.25rem 0 .6rem;
}
/* Button (CTA) je Zeile: in der Spalte der ausgeblendeten rechten Grafik
   (rechtsbündig, senkrecht mittig) oder unter dem Text. Farbe = Akzent. */
.steps-cta {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .85rem 1.5rem;
    border-radius: 12px;
    color: #fff;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: filter .15s;
}
.steps-cta:hover { color: #fff; filter: brightness(1.08); }
.steps-col-cta { display: flex; justify-content: flex-end; padding-left: 1rem; }
.steps-cta-wrap { margin-top: 1rem; }
/* Merkmal-Pills: Icon in Akzentfarbe + kurze Beschriftung, umrandet, in einer
   eigenen Zeile unter Text und Button. */
.steps-badges {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    margin-top: .9rem;
}
.steps-badge {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
    padding: .7rem 1.1rem;
    border: 1px solid #e3e6ea;
    border-radius: 12px;
    background: #fff;
    color: #1b2a4a;
    font-weight: 600;
    font-size: .95rem;
    line-height: 1.2;
    text-decoration: none;
}
.steps-badge i { font-size: 1.25rem; line-height: 1; }
a.steps-badge:hover { border-color: #c9d2de; color: #1b2a4a; }

/* Unter md (< 768 px, also XS und SM) fallen beide Grafik-Spalten weg: Sie
   würden gestapelt jeweils die volle Breite einnehmen und den Text weit nach
   unten drücken. Übrig bleibt die Textspalte, die dann automatisch die ganze
   Zeile füllt. */
@media (max-width: 767.98px) {
    .steps-row { padding: 1rem; }
    .steps-heading { font-size: 1.2rem; }
    .steps-module .steps-col-media { display: none; }
    .steps-col-cta { justify-content: flex-start; margin-top: .25rem; }
    .steps-cta { width: 100%; justify-content: center; }
    .steps-badge { flex: 1 1 calc(50% - .6rem); justify-content: center; }
}

/* Zierlinien seitlich der Bereichs-Überschrift (Schritte-Modul).
   Beide Linien wachsen per flex:1 in den freien Raum und laufen nach AUSSEN
   in Transparenz aus — der Verlauf zeigt also jeweils zur Überschrift hin.
   Farbe/Stärke setzt das Modul per Custom Property. */
.ds-title-rule-wrap {
    display: flex;
    align-items: center;
    gap: 1.25rem;
}
.ds-title-rule {
    flex: 1 1 0;
    min-width: 1.5rem;
    height: var(--ds-title-rule-width, 2px);
    border-radius: 999px;
}
/* Die eingefasste Überschrift darf keine eigenen Außenabstände mehr haben,
   sonst sitzen die Linien nicht mehr mittig auf ihrer Höhe. */
.ds-title-rule-wrap > :is(h1, h2, h3, h4, h5, h6) {
    margin: 0;
    text-align: center;
}
/* Feste Linienlänge (Admin gibt px vor): die Linien wachsen dann nicht mehr
   in den freien Raum, sondern stehen mit fixer Breite neben der Überschrift.
   Das Ganze wird zentriert, damit die Gruppe mittig bleibt. Die max-width
   verhindert, dass ein grosser px-Wert auf schmalen Displays die Überschrift
   aus dem Bild schiebt. */
.ds-title-rule-wrap.has-fixed-rule {
    justify-content: center;
}
.ds-title-rule-wrap.has-fixed-rule .ds-title-rule {
    flex: 0 0 auto;
    width: var(--ds-title-rule-length, 80px);
    min-width: 0;
    max-width: 30vw;
}
.ds-title-rule:first-child {
    background: linear-gradient(to right, transparent, var(--ds-title-rule-color, #c9d2de));
}
.ds-title-rule:last-child {
    background: linear-gradient(to left, transparent, var(--ds-title-rule-color, #c9d2de));
}
@media (max-width: 575.98px) {
    /* Auf schmalen Displays bleibt sonst kaum Platz für die Überschrift. */
    .ds-title-rule-wrap { gap: .75rem; }
    .ds-title-rule { min-width: .75rem; }
}
/* Im Textbereich unter md (< 768 px, also XS und SM) ohne Zierlinien: dort
   nimmt die Überschrift meist mehrere Zeilen ein, die Linien daneben wirken
   gequetscht. Nur die Linien entfallen — die Überschrift bleibt und wird als
   einziges verbliebenes Flex-Element mittig gesetzt. */
@media (max-width: 767.98px) {
    .textbereich-module .ds-title-rule { display: none; }
    .textbereich-module .ds-title-rule-wrap { justify-content: center; }
}

/* === Vorteile-Karten ================================================
   Gleich hohe Karten nebeneinander: Grafik oben auf getönter Fläche,
   darunter nummerierter Kreis + Überschrift, darunter Fließtext. */
.usp-card {
    height: 100%;
    display: flex;
    flex-direction: column;
    padding: 1rem 1rem 1.35rem;
}
.usp-card.has-shadow {
    box-shadow: 0 2px 10px rgba(16, 30, 54, .06);
}

/* Bildfläche: festes Seitenverhältnis, damit alle Karten gleich hoch
   starten — auch solange noch keine Grafik hinterlegt ist. Das Bild füllt
   sie randlos, sonst zeigt ein randvolles Motiv seine eigenen eckigen Ecken. */
.usp-card-media {
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1.1rem;
}
.usp-card-media.is-4x3  { aspect-ratio: 4 / 3; }
.usp-card-media.is-1x1  { aspect-ratio: 1 / 1; }
.usp-card-media.is-16x10 { aspect-ratio: 16 / 10; }
.usp-card-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
/* Variante für freigestellte Motive: ganz sichtbar, getönte Fläche als Rahmen. */
.usp-card-media.is-contain { padding: .75rem; }
.usp-card-media.is-contain img {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
}

/* Nummer und Überschrift in einer Zeile; die Nummer bleibt an der ERSTEN
   Textzeile hängen, auch wenn die Überschrift umbricht. */
.usp-card-head {
    display: flex;
    align-items: flex-start;
    gap: .65rem;
    margin-bottom: .75rem;
}
.usp-card-num {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: .9rem;
    font-weight: 700;
    line-height: 1;
    margin-top: .18em;
}
.usp-card-title {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.25;
    margin: 0;
}
.usp-card-body {
    color: #55606d;
    line-height: 1.6;
}
.usp-card-body p:last-child { margin-bottom: 0; }

@media (max-width: 575.98px) {
    .usp-card { padding: .85rem .85rem 1.1rem; }
    .usp-card-title { font-size: 1.1rem; }
}

/* === Hero: begrenzter Textblock ======================================
   Breite und Platzierung setzt das Modul inline (--hero-text-width plus
   margin-left/right:auto). Unter md wird die Begrenzung aufgehoben: ein auf
   30 % geschrumpfter Block wäre auf dem Handy nicht mehr lesbar. */
.hero-module .hero-text {
    width: var(--hero-text-width, 100%);
    max-width: 100%;
}
/* Absätze ohne Bootstrap-Abstand (1rem): der Editor (Quill) zeigt Zeilen
   direkt untereinander, das Frontend soll genauso aussehen. Leere Absätze
   (<p><br></p>) bleiben als bewusste Leerzeilen erhalten. */
.hero-module .hero-text p { margin-bottom: 0; }
@media (max-width: 767.98px) {
    .hero-module .hero-text {
        width: 100%;
    }
}

/* === Hero: Kästen unter dem Text =====================================
   Eine Reihe kleiner Karten (Grafik + Überschrift + Zeile), die im Textblock
   liegt und deshalb dessen Breite und Platzierung erbt. flex-wrap statt
   Grid: bei drei Kästen soll die Reihe auf schmalen Schirmen einfach
   umbrechen, ohne dass eine Spaltenzahl gepflegt werden muss.
   Der Kasten-Hintergrund kommt inline aus dem Modul (Farbe + Deckkraft),
   hier steht nur der Rückfall für den Fall, dass keiner gesetzt ist. */
.hero-module .hero-boxes {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
    margin-top: 1.5rem;
}
.hero-module .hero-box {
    flex: 0 1 auto;
    min-width: 8.5rem;
    max-width: 13rem;
    padding: 1rem .9rem;
    border-radius: .75rem;
    text-align: center;
    background: rgba(255, 255, 255, .08);
}
.hero-module .hero-box-icon {
    display: block;
    font-size: 2rem;
    line-height: 1;
    margin-bottom: .6rem;
}
/* Feste Höhe statt fester Breite: so stehen Grafiken unterschiedlicher
   Seitenverhältnisse trotzdem auf einer Linie. */
.hero-module .hero-box-img {
    display: block;
    height: 2.5rem;
    width: auto;
    max-width: 100%;
    margin: 0 auto .6rem;
    object-fit: contain;
}
.hero-module .hero-box-title {
    font-weight: 700;
    line-height: 1.2;
}
.hero-module .hero-box-text {
    font-size: .8125rem;
    opacity: .8;
    margin-top: .35rem;
}
@media (max-width: 575.98px) {
    /* Auf dem Handy nebeneinander zu schmal — zwei pro Zeile reichen. */
    .hero-module .hero-box { flex: 1 1 8rem; max-width: none; }
}

/* ============================================================
   Mobil: kein „Gummiband" — die Seite darf sich nicht seitlich
   verschieben lassen, wenn ein Element breiter ist als der
   Viewport. overflow-x: clip statt hidden: clip erzeugt KEINEN
   Scroll-Container und laesst position:sticky (Header) intakt.
   overscroll-behavior-x unterbindet den seitlichen Bounce.
   ============================================================ */
html, body {
    overflow-x: clip;
    overscroll-behavior-x: none;
}
@supports not (overflow-x: clip) {
    /* Alte Browser: hidden als Notloesung (kann sticky beeintraechtigen). */
    html, body { overflow-x: hidden; }
}


/* === Karten-Slider (card_slider): Bild, Titel, Preis, Text, Badge ==========
   Nutzt Track/Pfeile/Autoplay des Kategorie-Sliders (.category-slider-*).
   Akzent (Preis, Link) und Badge-Fläche kommen als CSS-Variablen vom Modul. */
.cs-title { font-size: 1.7rem; font-weight: 800; color: #0f172a; }
.cs-more { color: var(--cs-accent, #1d6ff2); font-weight: 700; text-decoration: none; font-size: 1.05rem; }
.cs-more:hover { text-decoration: underline; color: var(--cs-accent, #1d6ff2); }
.cs-card {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    width: 100%; height: 100%; padding: 1.1rem .9rem 1rem; color: #0f172a;
    border: 1px solid #e5e7eb; border-radius: .9rem;
    box-shadow: 0 6px 18px rgba(16, 24, 40, .06);
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}
a.cs-card:hover { transform: translateY(-4px); border-color: var(--cs-accent, #1d6ff2); box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.12); color: #0f172a; }
.cs-media { height: 150px; width: 100%; display: flex; align-items: center; justify-content: center; margin-bottom: .75rem; }
.cs-media img { max-height: 100%; max-width: 100%; object-fit: contain; }
.cs-media .bi { font-size: 4.5rem; line-height: 1; color: var(--cs-accent, #1d6ff2); }
.cs-heading { font-weight: 800; font-size: 1.15rem; line-height: 1.2; margin-bottom: .35rem; overflow-wrap: anywhere; }
.cs-price { color: var(--cs-accent, #1d6ff2); font-weight: 800; font-size: 1.4rem; margin-bottom: .3rem; }
.cs-body { color: #6b7280; font-size: .95rem; line-height: 1.35; }
.cs-badge { margin-top: auto; padding-top: .75rem; width: 100%; display: flex; justify-content: center; }
.cs-badge-pill {
    display: inline-flex; align-items: center; gap: .5rem; max-width: 100%;
    background: var(--cs-badge-bg, #eef4ff); color: var(--cs-accent, #1d6ff2);
    border-radius: 999px; padding: .35rem .9rem .35rem .4rem; font-size: .9rem; font-weight: 600; line-height: 1.2;
}
.cs-badge-icon {
    width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
    background: var(--cs-accent, #1d6ff2); color: #fff;
    display: inline-flex; align-items: center; justify-content: center; font-size: .8rem;
}
.card-slider-module .category-slider-track { padding-top: .5rem; padding-bottom: 1rem; }
/* Ohne Pfeile keine Randspur — der Track nutzt die volle Breite. */
.category-slider.no-arrows .category-slider-track { margin-left: 0; margin-right: 0; }
.card-slider-module .category-slider-item { display: flex; }
@media (max-width: 575.98px) { .cs-title { font-size: 1.3rem; } .cs-media { height: 120px; } }

/* === Ablauf-Duo (process_duo): zwei Abläufe nebeneinander ================
   Je Panel getönte Fläche mit Kopf (Symbol + Überschrift + Unterzeile in der
   Akzentfarbe) und einer Reihe Schritte: gefüllter Nummernkreis, Symbol, Titel,
   Kurztext; dazwischen Pfeile. Akzentfarbe kommt als --pduo-accent vom Panel. */
.pduo-grid { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; }
.pduo-grid.is-single { grid-template-columns: 1fr; }
.pduo-panel { padding: 1.4rem 1.4rem 1.6rem; }
.pduo-head { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.25rem; color: var(--pduo-accent); }
.pduo-head-icon { font-size: 2.6rem; line-height: 1; flex-shrink: 0; }
.pduo-title { font-weight: 800; font-size: 1.45rem; line-height: 1.15; }
.pduo-sub { font-size: 1rem; opacity: .9; margin-top: .15rem; }
.pduo-steps { display: flex; align-items: flex-start; gap: .25rem; }
.pduo-step { flex: 1 1 0; min-width: 0; text-align: center; display: flex; flex-direction: column; align-items: center; }
.pduo-num {
    width: 46px; height: 46px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--pduo-accent); color: #fff; font-weight: 800; font-size: 1.35rem;
    margin-bottom: .75rem;
}
.pduo-step-icon { font-size: 2.4rem; line-height: 1; color: var(--pduo-accent); margin-bottom: .55rem; }
.pduo-step-title { font-weight: 700; font-size: 1.05rem; margin-bottom: .3rem; }
.pduo-step-body { font-size: .9rem; line-height: 1.4; opacity: .9; }
.pduo-arrow { flex: 0 0 auto; color: var(--pduo-accent); font-size: 1.3rem; line-height: 1; padding-top: 12px; }
@media (max-width: 991.98px) {
    .pduo-grid { grid-template-columns: 1fr; }
}
@media (max-width: 575.98px) {
    .pduo-steps { flex-wrap: wrap; gap: .75rem 0; }
    .pduo-step { flex: 1 1 45%; }
    .pduo-arrow { display: none; }
    .pduo-title { font-size: 1.2rem; }
}

/* === Bestellschritte (order_steps): nummerierte Schritt-Karten ============
   Reihe gleich breiter Karten (Nummer + Icon oben, Titel, Kurztext), dazwischen
   Verbindungslinien mit Punkt auf Hoehe der Kopfzeile. Farben (Akzent, Rahmen,
   Hintergrund) setzt das Modul inline aus der Config. */
.order-steps-track { display: flex; align-items: stretch; gap: 14px; }
.order-steps-card {
    flex: 1 1 0;
    min-width: 0;
    padding: 1.1rem 1rem;
    text-align: center;
}
.order-steps-card.has-shadow { box-shadow: 0 6px 18px rgba(16, 24, 40, .06); }
.order-steps-head {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .6rem;
    min-height: 44px;
    margin-bottom: .55rem;
}
.order-steps-num {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    font-size: .9rem;
    background: #f1f3f6;
    color: #5b6572;
    border: 1px solid #d6dce4;
}
.order-steps-icon { max-height: 40px; max-width: 64px; object-fit: contain; }
.order-steps-title { font-size: 1.02rem; font-weight: 700; margin: 0 0 .35rem; }
.order-steps-body { font-size: .9rem; line-height: 1.45; }
.order-steps-link {
    flex: 0 0 26px;
    align-self: center;
    position: relative;
    height: 2px;
    background: #d6dce4;
}
.order-steps-link span {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #fff;
    border: 2px solid #c3cbd6;
}
/* Unter md stapeln die Karten, Verbindungslinien entfallen. */
@media (max-width: 767.98px) {
    .order-steps-track { flex-direction: column; gap: .75rem; }
    .order-steps-link { display: none; }
}
