/* Teaser Slider — komponentenspezifische Variables (überschreibbar via
   Tier-CSS in html/assets/css/tier/{basic,pro}/variables.css). */
:root {
    /* Hero-Variant (Startseite): volle Höhe pro Breakpoint */
    --teaser-hero-min-height:        70vh;
    --teaser-hero-min-height-tablet: 60vh;
    --teaser-hero-min-height-mobile: 50vh;
    /* Handy: Hero mindestens Bildschirm minus Kopf (s. Mobile-Regel). Reserve = Kopfhöhe mit Topbar
       (ips: 40 + 64 px); ein Paket mit anderem Kopf passt nur diese Variable an. */
    --teaser-hero-header-reserve:    6.5rem;
    /* Compact-Variant (Subpages): niedriger, schlankerer Content */
    --teaser-compact-min-height:        35vh;
    --teaser-compact-min-height-tablet: 32vh;
    --teaser-compact-min-height-mobile: 28vh;
    --teaser-compact-content-max-width: 700px;
    /* Welcome-Variant: vollflächiger Wegweiser-Hero mit mehreren CTAs.
       Auto-aktiv wenn ein Slide buttons[]-Array hat statt btn/link. */
    --teaser-welcome-min-height:        100dvh;
    --teaser-welcome-min-height-fallback: 100vh;
    --teaser-welcome-content-max-width: 60rem;
    --teaser-welcome-buttons-gap:       var(--space-4);
    --teaser-welcome-btn-bg:            hsl(0 0% 100% / 0.12);
    --teaser-welcome-btn-bg-hover:      hsl(0 0% 100% / 0.22);
    --teaser-welcome-btn-border:        hsl(0 0% 100% / 0.5);
    --teaser-welcome-btn-color:         hsl(0 0% 100%);
}

#teaser-slider {
    position: relative;
    overflow: hidden;
}

/* Alle Slides liegen im SELBEN Grid-Feld übereinander → der Slider ist so hoch wie die höchste
   Slide, kürzere füllen die Höhe (Inhalt bleibt per align-items mittig). Vorher stand nur die aktive
   Slide im Fluss (die übrigen absolut): der Teaser sprang beim Wechsel in der Höhe, am Handy um bis
   zu 100 px (ips.saarland 360 px: 638 / 672 / 738 px, gemessen 01.10.2026). Die Schiebe-Effekte
   setzen die beteiligten Slides weiter absolut (inset: 0) — Bezug ist der Track, der jetzt die volle
   Höhe hat. */
#teaser-slider .track {
    position: relative;
    display: grid;
}

#teaser-slider .slide {
    grid-area: 1 / 1;
    position: relative;
    min-height: var(--teaser-hero-min-height);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.8s ease;
    pointer-events: none;
}

#teaser-slider .slide.active {
    position: relative;
    opacity: 1;
    pointer-events: auto;

}

/* Background */
#teaser-slider .bg {
    position: absolute;
    inset: 0;
    z-index: 1;

}

#teaser-slider .bg::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--scrim-light);
}

#teaser-slider .bg img,
#teaser-slider .bg video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scale(1.08);
    transition: transform 8s ease-out;
}

#teaser-slider .slide.active .bg img,
#teaser-slider .slide.active .bg video {
    transform: scale(1.01);
}

/* Content */
#teaser-slider .content {
    position: relative;
    z-index: 3;
    text-align: center;
    color: var(--color-text-inverse);;
    padding: 10rem 2rem 3rem;
    max-width: 900px;
}

#teaser-slider .label {
    display: block;
    font-size: 0.75rem;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.7);
    margin-bottom: 1.5rem;
    opacity: 0;
    transform: translateY(30px);
}

#teaser-slider h2 {
    font-size: clamp(2.2rem, 5vw, 4rem);
    font-weight: 300;
    line-height: 1.1;
    letter-spacing:0;
    margin: 0 0 1.5rem;
    color: var(--color-text-inverse);;
    opacity: 0;
    transform: translateY(30px);
}

#teaser-slider hr {
    width: 80px;
    height: 2px;
    border: none;
    background: rgba(255, 255, 255, 0.5);
    margin: 0 auto 1.5rem;
    opacity: 0;
    transform: scaleX(0);
}

#teaser-slider .content p {
    font-size: 1.1rem;
    line-height: 1.8;
    color: rgba(255, 255, 255, 0.85);
    font-weight: 300;
    max-width: 650px;
    margin: 0 auto 2rem;
    opacity: 0;
    transform: translateY(30px);
}

#teaser-slider .content a {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem 2rem;
    color: var(--color-primary, #333);
    background: #fff;
    text-decoration: none;
    font-size: 0.85rem;
    letter-spacing: var(--tracking);
    text-transform: uppercase;
    transition: all 0.3s ease;
    opacity: 0;
    transform: translateY(30px);
}

#teaser-slider .content a:hover {
    background: var(--color-primary, #333);
    color: var(--color-text-inverse);;
}

/* Animations */
#teaser-slider .slide.active .label     { animation: teaserFadeUp 0.8s ease forwards 0.3s; }
#teaser-slider .slide.active h2         { animation: teaserFadeUp 0.8s ease forwards 0.5s; }
#teaser-slider .slide.active hr         { animation: teaserScaleX 0.6s ease forwards 0.7s; }
#teaser-slider .slide.active .content p { animation: teaserFadeUp 0.8s ease forwards 0.9s; }
#teaser-slider .slide.active .content a { animation: teaserFadeUp 0.8s ease forwards 1.1s; }

@keyframes teaserFadeUp {
    to { opacity: 1; transform: translateY(0); }
}

@keyframes teaserScaleX {
    to { opacity: 1; transform: scaleX(1); }
}

/* Prev / Next */
#teaser-slider .prev,
#teaser-slider .next {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 10;
    width: 50px;
    height: 50px;
    background: var(--scrim-light);
    color: var(--color-text-inverse);;
    border: none;
    border-radius: 50%;
    font-size: 1.5rem;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.3s ease, background 0.3s ease;
    display: flex;
    align-items: center;
    justify-content: center;
}

#teaser-slider:hover .prev,
#teaser-slider:hover .next {
    opacity: 1;
}

/* Pfeil-Sichtbarkeit aus der Kunden-Config (teaser_arrows, Migration 5037).
   'hover' = Regeln oben, der Default und das Verhalten von vor dem 09.09.2026.
   'always' = dauerhaft sichtbar, 'none' = gar nicht (die Indikatoren bleiben,
   und Wischen auf dem Touchgeraet funktioniert weiterhin). */
#teaser-slider[data-arrows="always"] .prev,
#teaser-slider[data-arrows="always"] .next {
    opacity: 1;
}

#teaser-slider[data-arrows="none"] .prev,
#teaser-slider[data-arrows="none"] .next {
    display: none;
}

/* ============================================================
   Uebergang: Schieben statt Ueberblenden (teaser_effect)
   ============================================================
   Der Default 'fade' steht oben (.slide { opacity }) und bleibt unberuehrt.
   Beim Schieben traegt jeder Slide volle Deckkraft und wird stattdessen aus
   dem Bild geschoben. Die RICHTUNG setzt teaser.js ueber zwei Klassen, weil
   CSS allein nicht weiss, ob es vorwaerts oder rueckwaerts geht:

     .is-entering  der neue Slide, VOR dem Wechsel auf seine Startposition
                   gesetzt (rechts bzw. unten ausserhalb; bei 'zurueck'
                   spiegelverkehrt ueber .is-reverse am Slider).
     .is-leaving   der alte Slide, der in die Gegenrichtung hinauslaeuft.

   Ohne diese beiden Klassen (JS aus, Erstaufbau) steht der aktive Slide
   einfach an Position 0 und alle anderen daneben - die Seite bleibt also
   auch ohne JavaScript brauchbar. */
/* ⚠ Sichtbar ist NUR, wer am Wechsel beteiligt ist.
   Das ist der Kern: Bei `fade` sind inaktive Slides `opacity: 0` - sie koennen nicht stoeren,
   egal wo sie liegen. Beim Schieben brauchen sie Deckkraft, sonst saehe man die Bewegung nicht;
   sie pauschal auf `opacity: 1` zu setzen war der Fehler (gemeldet 09.09.2026 mit Screenshot:
   "am rechten Rand ist bereits das naechste Bild zu sehen, links ein weiteres").
   Denn `translateX(100%)` rechnet mit der EIGENEN Breite: geht die Geometrie nicht exakt auf -
   Slide schmaler als der Track, Rundung, Scrollbar -, steht ein unbeteiligter Nachbar mit voller
   Deckkraft am Rand. Clipping allein rettet das nicht.
   Deshalb: unbeteiligte Slides bleiben unsichtbar wie bei `fade`; Deckkraft bekommen nur der
   aktive und die beiden, die gerade laufen. Damit ist das Symptom unabhaengig von jeder
   Breitenabweichung ausgeschlossen. */
#teaser-slider[data-effect^="slide-"] .slide {
    opacity: 0;
    transition: transform 0.8s ease;
}

#teaser-slider[data-effect^="slide-"] .slide.active,
#teaser-slider[data-effect^="slide-"] .slide.is-leaving,
#teaser-slider[data-effect^="slide-"] .slide.is-entering {
    opacity: 1;
}

/* Zwei Absicherungen gegen sichtbare Nachbar-Slides (gemeldet 09.09.2026 an der ersten
   Live-Instanz: "am rechten Rand ist bereits das naechste Bild zu sehen").
   
   1. Der Track schneidet selbst ab. `overflow: hidden` sitzt sonst nur am #teaser-slider;
      ist der Track aus irgendeinem Grund schmaler als der Slider - Layout-Breite, Scrollbar,
      ein Kunden-Overlay -, ragen die verschobenen Slides in den sichtbaren Bereich, und man
      sieht sie neben dem aktiven stehen.
   2. Jeder Slide belegt die volle Track-Breite. `translateX(100%)` rechnet mit der EIGENEN
      Breite: ist ein Slide schmaler als der Container, schiebt 100% ihn nicht weit genug
      hinaus - er bleibt am Rand stehen. Mit `left/right: 0` sind alle Slides exakt so breit
      wie der Track, und 100% traegt sicher heraus. */
#teaser-slider[data-effect^="slide-"] .track {
    overflow: hidden;
}

#teaser-slider[data-effect^="slide-"] .slide {
    left: 0;
    right: 0;
    width: auto;
}

/* Ruhelage: alles ausserhalb, der aktive Slide in der Mitte. */
#teaser-slider[data-effect="slide-horizontal"] .slide        { transform: translateX(100%); }
#teaser-slider[data-effect="slide-vertikal"]   .slide        { transform: translateY(100%); }
#teaser-slider[data-effect^="slide-"]          .slide.active { transform: translate(0, 0); }

/* Der eingehende Slide wird ohne Animation auf seine Startseite gesetzt
   (transition: none), damit der anschliessende Lauf nach 0 sichtbar wird. */
#teaser-slider[data-effect^="slide-"] .slide.is-entering { transition: none; }
#teaser-slider[data-effect="slide-horizontal"] .slide.is-entering { transform: translateX(100%); }
#teaser-slider[data-effect="slide-vertikal"]   .slide.is-entering { transform: translateY(100%); }
#teaser-slider[data-effect="slide-horizontal"].is-reverse .slide.is-entering { transform: translateX(-100%); }
#teaser-slider[data-effect="slide-vertikal"].is-reverse   .slide.is-entering { transform: translateY(-100%); }

/* Der ausgehende Slide laeuft in die Gegenrichtung hinaus (Deckkraft: Regel oben). */
#teaser-slider[data-effect="slide-horizontal"] .slide.is-leaving { transform: translateX(-100%); }
#teaser-slider[data-effect="slide-vertikal"]   .slide.is-leaving { transform: translateY(-100%); }
#teaser-slider[data-effect="slide-horizontal"].is-reverse .slide.is-leaving { transform: translateX(100%); }
#teaser-slider[data-effect="slide-vertikal"].is-reverse   .slide.is-leaving { transform: translateY(100%); }

/* Stillgelegt: waehrend das JS die Hilfsklassen abraeumt. Ohne das laeuft der ausgelaufene
   Slide von seiner Endposition (links aussen) in die Ruhelage (rechts aussen) - also quer durchs
   Bild ueber den aktiven Slide hinweg. `!important`, weil die Regel gegen die Effekt-Regeln oben
   gewinnen muss, die dieselbe Spezifitaet haben. */
#teaser-slider .slide.no-anim {
    transition: none !important;
}

/* Beide beteiligten Slides muessen waehrend des Laufs sichtbar sein - die
   Grundregel blendet inaktive per pointer-events/Stapelposition aus. */
#teaser-slider[data-effect^="slide-"] .slide.is-leaving,
#teaser-slider[data-effect^="slide-"] .slide.is-entering {
    position: absolute;
    inset: 0;
}

/* Bewegung respektiert die Systemeinstellung: wer weniger Animation will,
   bekommt den harten Schnitt statt eines 0,8-Sekunden-Laufs. Der Ken-Burns-
   Zoom faellt aus demselben Grund weg. */
@media (prefers-reduced-motion: reduce) {
    #teaser-slider[data-effect^="slide-"] .slide,
    #teaser-slider .slide,
    #teaser-slider .slide .bg img,
    #teaser-slider .slide .bg video {
        transition: none;
    }
}

#teaser-slider .prev:hover,
#teaser-slider .next:hover {
    background: var(--scrim-heavy);
}

#teaser-slider .prev { left: 1rem; }
#teaser-slider .next { right: 1rem; }

/* Indicators */
#teaser-slider .indicators {
    position: absolute;
    bottom: 2rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    display: flex;
    gap: 0.75rem;
    /* Der Knopf ist höher als der Balken (s. u.) → um die Hälfte der Differenz nach unten, damit der
       Balken dort sitzt, wo `bottom` es sagt (auch bei Design-Paketen, die nur `bottom` setzen). */
    margin-bottom: calc((var(--indicator-bar) - var(--indicator-hit)) / 2);
    --indicator-bar: 3px;
    --indicator-hit: 1.5rem;
}

/* Trefferfläche = der KNOPF selbst (24px hoch), sichtbar ist nur der 3px-Balken in der Mitte:
   Polsterung oben/unten + background-clip: content-box. Vorher war der Knopf 3px hoch und die
   Fläche nur per ::after erweitert — Lighthouse misst aber die Box des Elements, nicht das
   Pseudo-Element („Tippziele zu klein", ips.saarland 01.10.2026).
   ⚠ `!important` am Clip ist Absicht: Design-Pakete färben den Balken per Kurzschreibweise
   (`button.active { background: … }`), und die setzt background-clip still auf border-box zurück —
   dann war die ganze 24px-Fläche weiß statt des Balkens (Vorfall ips, 01.10.2026). Die Farbe dürfen
   Pakete weiter setzen, nur der Zuschnitt ist fest. */
#teaser-slider .indicators button {
    box-sizing: border-box;
    width: 50px;
    height: var(--indicator-hit);
    padding: calc((var(--indicator-hit) - var(--indicator-bar)) / 2) 0;
    border: none;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.3);
    background-clip: content-box !important;
    cursor: pointer;
    position: relative;
}

#teaser-slider .indicators button::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    height: var(--indicator-bar);
    margin-top: calc(var(--indicator-bar) / -2);
    width: 0;
    background: #fff;
    transition: width 0s;
}

#teaser-slider .indicators button.active {
    background: rgba(255, 255, 255, 0.5);
}

#teaser-slider .indicators button.active::before {
    width: 100%;
    transition: width 6s linear;
}

/* Mobile */
@media screen and (max-width: 44.999rem) {
    /* Bildschirmfüllend (minus Kopf), damit die Höhe NICHT am Text hängt: Die höchste Slide maß bei ips
       mit Ersatzschrift 619, mit Hausschrift 652 px — kam die Schrift nach dem ersten Bild, wuchs der Teaser
       und der Text rückte nach (CLS 0,03–0,09, gemessen 01.10.2026). max(): Pakete dürfen die Höhe über
       --teaser-hero-min-height-mobile weiter anheben, aber nicht unter den Bildschirm drücken (ips setzt 60vh).
       svh statt dvh: dvh wächst beim Scrollen mit der Adressleiste mit — das wäre wieder ein Sprung.
       Grenze: Ist der Text höher als der Bildschirm (kleine Handys, lange Texte), entscheidet weiter er. */
    #teaser-slider .slide {
        min-height: var(--teaser-hero-min-height-mobile);
        min-height: max(var(--teaser-hero-min-height-mobile), calc(100vh - var(--teaser-hero-header-reserve)));
        min-height: max(var(--teaser-hero-min-height-mobile), calc(100svh - var(--teaser-hero-header-reserve)));
    }

    #teaser-slider .content {
        padding-top: 6rem;
    }

    /* CTA: Inline-Padding auf Mobile reduzieren (nutzt denselben Hebel wie .btn).
       Die Basis-Regel #teaser-slider .content a (padding: 1rem 2rem) hat höhere
       Spezifität als der globale .btn-Mobile-Fix → hier gezielt nachziehen. */
    #teaser-slider .content a {
        padding-inline: var(--btn-padding-inline-mobile);
    }

    #teaser-slider .indicators {
        bottom: 1rem;
    }

    #teaser-slider .indicators button {
        width: 2rem;
    }

    #teaser-slider .prev,
    #teaser-slider .next {
        width: 2.5rem;
        height: 2.5rem;
        font-size: 1rem;
    }
}

/* Tablet */
@media screen and (min-width: 45rem) and (max-width: 79.499rem) {
    #teaser-slider .slide {
        min-height: var(--teaser-hero-min-height-tablet);
    }

    #teaser-slider .content {
        padding-top: 8rem;
    }

    #teaser-slider .indicators button {
        width: 2.25rem;
    }
}

/* ============================================================
   Compact Variant — Subpage-Teaser (niedriger, schlankere Typo).
   Aktiviert wenn FrontendView page !== 'home' rendert.
   ============================================================ */

#teaser-slider.teaser-compact .slide {
    min-height: var(--teaser-compact-min-height);
}

#teaser-slider.teaser-compact .content {
    padding: 4rem 2rem 2rem;
    max-width: var(--teaser-compact-content-max-width);
}

#teaser-slider.teaser-compact h2 {
    font-size: clamp(1.6rem, 3.5vw, 2.6rem);
    margin-bottom: 1rem;
}

#teaser-slider.teaser-compact .label {
    margin-bottom: 1rem;
}

#teaser-slider.teaser-compact .content p {
    font-size: 1rem;
    margin-bottom: 1.5rem;
}

#teaser-slider.teaser-compact hr {
    margin-bottom: 1rem;
}

@media screen and (max-width: 44.999rem) {
    #teaser-slider.teaser-compact .slide {
        min-height: var(--teaser-compact-min-height-mobile);
    }

    #teaser-slider.teaser-compact .content {
        padding-top: 3rem;
    }
}

@media screen and (min-width: 45rem) and (max-width: 79.499rem) {
    #teaser-slider.teaser-compact .slide {
        min-height: var(--teaser-compact-min-height-tablet);
    }

    #teaser-slider.teaser-compact .content {
        padding-top: 3.5rem;
    }
}

/* ============================================================
   Welcome Variant — vollflächiger Wegweiser-Hero mit 2+ CTAs.
   Auto-aktiv wenn der Slide ein buttons[]-Array hat (siehe Teaser.php).
   ============================================================ */

#teaser-slider.teaser-welcome .slide {
    min-height: var(--teaser-welcome-min-height-fallback);
    min-height: var(--teaser-welcome-min-height);
}

#teaser-slider.teaser-welcome .content {
    max-width: var(--teaser-welcome-content-max-width);
}

#teaser-slider.teaser-welcome .buttons {
    display: flex;
    gap: var(--teaser-welcome-buttons-gap);
    justify-content: center;
    flex-wrap: wrap;
}

#teaser-slider.teaser-welcome .buttons .btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-8);
    background: var(--teaser-welcome-btn-bg);
    color: var(--teaser-welcome-btn-color);
    border: 1px solid var(--teaser-welcome-btn-border);
    border-radius: var(--btn-radius);
    text-decoration: none;
    font-weight: 500;
    letter-spacing: var(--button-tracking);
    transition: background var(--transition), transform var(--transition);
    backdrop-filter: blur(0.5rem);
}

#teaser-slider.teaser-welcome .buttons .btn:hover {
    background: var(--teaser-welcome-btn-bg-hover);
    transform: translateY(-0.125rem);
}

@media (max-width: 44.999rem) {
    #teaser-slider.teaser-welcome .buttons {
        flex-direction: column;
        width: 100%;
    }
    #teaser-slider.teaser-welcome .buttons .btn {
        justify-content: center;
    }
}
