/* ============================================================
   Einheiten-Policy: rem fuer Typografie/Abstaende/Groessen (skaliert mit der
   Root-Schriftgroesse - respektiert Browser-Zoom/OS-Textgroesse, UND gibt
   uns einen einzigen zentralen Hebel, die App z.B. fuer das Rezeptions-
   Display groesser zu skalieren, siehe html { font-size: ... }). px NUR
   fuer Faelle, in denen rem keinen Vorteil bringt bzw. echte Pixel-Praezision
   zaehlt:
   - Media-Query-Breakpoints (768px, 767.98px, 1199.98px - Konvention,
     unabhaengig von Text-Skalierung)
   - Border-/Outline-Breiten (inkl. der Border-Dreieck-Technik beim
     Zeiger-Pfeil) - Haarlinien-Schaerfe, kein sinnvoller Skalierungs-Nutzen
   - box-shadow-Werte (Tiefen-Effekt, nicht text-relativ)
   - Scrollbar-Pseudo-Elemente (::-webkit-scrollbar & Co. - eher
     Browser-Chrome als Typografie) sowie der 999px-"Pille"-Trick fuer
     border-radius (beliebig gross gewaehlt, keine echte Groessenangabe)
   - transform-Mikro-Nudges (z.B. der 1px-Hover-Lift) - bewusste
     Pixel-Praezision fuer einen kaum wahrnehmbaren Effekt
   - SVG-interne Werte (Kartenansicht: eigenes viewBox-Koordinatensystem,
     nicht an die Root-Schriftgroesse der Seite gekoppelt)
   letter-spacing bleibt bewusst bei em (nicht rem): em ist hier relativ zur
   Schriftgroesse des jeweiligen Elements SELBST richtig - skaliert die Uhr
   im Icon-only-Modus (kleinere font-size) automatisch mit, rem bliebe
   dagegen immer an der Root-Groesse haengen.
   ============================================================ */
:root {
    /* ============================================================
       MARKEN-FARBEN - fuers Umstyling reichen im Idealfall diese zwei
       Werte. Wer nichts an app.css aendern moechte: dieselben zwei
       Variablen (plus optional --bs-primary-rgb) einfach in
       public/custom.css erneut setzen - die Datei wird in layout.twig
       NACH app.css geladen und gewinnt daher automatisch.
       ============================================================ */
    --cbm-brand-primary: #4f46e5;   /* Haupt-Akzent: aktiver Navi-Punkt, Buttons, Links */
    --cbm-brand-secondary: #ec4899; /* Zweit-Akzent: Uhr-Verlauf, Hover-Töne */
    /* Das Sidebar-Logo (Appception-Marke) haengt bewusst NICHT an diesen
       Variablen - siehe Kommentar bei .cbm-sidebar__logo .cbm-logo-icon
       weiter unten und sidebar.twig. */

    --cbm-sidebar-width: 15rem;      /* 240px */
    --cbm-sidebar-width-icons: 4.75rem; /* 76px */
    --cbm-sidebar-bg: #262c3d;
    --cbm-sidebar-bg-darker: #1e2331;
    --cbm-sidebar-fg: #e7ebf3;
    --cbm-sidebar-fg-muted: #9aa5b8;
    --cbm-accent: var(--cbm-brand-primary);

    --cbm-ampel-grau: #9aa0a8;
    --cbm-ampel-gruen: #2eb872;
    --cbm-ampel-rot: #e5484d;

    /* Hellgelbe "heute"-Markierung - eine gemeinsame Quelle fuer Kalender
       (ueberschreibt FullCalendars eigene --fc-today-bg-color, siehe unten)
       UND Timeline (.cbm-tl-today-marker), damit beide Ansichten exakt
       denselben Farbton verwenden. */
    --cbm-today-bg-color: rgba(255, 220, 40, .15);

    /* Bootstraps eigene "primary"-Farbe (Buttons, Links, Fokus-Ringe, Checkboxen
       usw. app-weit) auf denselben Marken-Akzent ziehen, statt Bootstraps
       Standardblau. --bs-primary-rgb kann CSS nicht automatisch aus dem Hex-Wert
       berechnen - bei Aenderung von --cbm-brand-primary bitte manuell mitziehen. */
    --bs-primary: var(--cbm-brand-primary);
    --bs-primary-rgb: 79, 70, 229;
    --bs-link-color: var(--cbm-brand-primary);
    --bs-link-color-rgb: 79, 70, 229;
    --bs-link-hover-color: var(--cbm-brand-secondary);
}

/* ============================================================
   Globale Ebenen (z-index) - eine Uebersicht an EINER Stelle, statt vieler
   verstreuter Einzelwerte, damit neue Ueberlagerungen sich sauber
   einordnen lassen statt Zufallswerte zu raten. Bootstrap 5.3 legt seine
   eigene Skala als CSS-Variablen auf :root ab (--bs-zindex-*), unsere
   eigenen Ebenen bauen bewusst DARUM HERUM statt sie zu ueberschreiben:

     (auto) .cbm-content        - normale Content-Flaeche, bewusst OHNE
                                   eigenen z-index (siehe Kommentar dort -
                                   ein Flex-Item MIT z-index wuerde einen
                                   Stacking-Context erzeugen und darin
                                   verschachtelte position:fixed-Elemente
                                   wie .cbm-fab einsperren)
        20  .cbm-sidebar         - nur ab Tablet-Breite (sticky, kein
                                   Offcanvas mehr); auf Mobile UNGESETZT,
                                   siehe Kommentar dort
      1030  .cbm-fab             - fliegender "+"-Button (Kartenansicht)
      1040  .cbm-burger          - mobiler Menu-Button
      1040  --bs-zindex-offcanvas-backdrop (Bootstrap, unveraendert)
      1045  --bs-zindex-offcanvas (Bootstrap, unveraendert - das ist
                                   .cbm-sidebar auf Mobile)
      1050  --bs-zindex-modal-backdrop (Bootstrap, unveraendert)
      1055  --bs-zindex-modal    (Bootstrap, unveraendert) - alle
                                   "Basis"-Modals (Login/Buchung/Raum-Modal/
                                   Administration-Formulare)
      1070  .cbm-modal-stacked-backdrop - Backdrop von Bestaetigungs-Dialogen
                                   (Loeschen/Dangerzone), die IMMER aus einem
                                   bereits offenen Basis-Modal heraus
                                   geoeffnet werden - Bootstrap selbst kennt
                                   keine gestapelten Modals (alle .modal/
                                   .modal-backdrop teilen denselben
                                   z-index), siehe app.js
      1075  .cbm-modal-stacked   - dito, das Bestaetigungs-Modal selbst
      1070  --bs-zindex-popover, 1080 --bs-zindex-tooltip (Bootstrap,
                                   unveraendert - liegen ohnehin ueber allem)
      2000  .cbm-splash          - Ladebildschirm, deckt initial wirklich
                                   alles ab
      2100  .cbm-devtools        - nicht verlinkte Dev-Werkzeuge (siehe
                                   assets/js/dev-tools.js), bewusst ueber
                                   allem inkl. Splash, da per Hash-Route
                                   (#generate_password/#generate_bigseed)
                                   jederzeit unabhaengig vom Ladezustand
                                   aufrufbar
   ============================================================ */

html, body {
    height: 100%;
}

body {
    background: #f4f6fa;
}

.cbm-app {
    display: flex;
    min-height: 100vh;
}

@media (min-width: 768px) {
    /* Ab Tablet-Breite ("auf Displays"): die App ist eine fixe, nie selbst
       scrollende Buehne (wie schon die Sidebar per position:sticky+100vh
       weiter unten) - Scrollen passiert NUR noch innerhalb der einen Card
       jeder Ansicht (siehe .cbm-content-Regeln weiter unten). Auf Mobile
       bleibt bewusst normales Seiten-Scrollen (das Offcanvas-Burgermenue
       macht die feste Buehne dort unpraktikabel, der Platz ist ohnehin knapp). */
    .cbm-app {
        height: 100vh;
        overflow: hidden;
    }
}

/* --- Sidebar / Navigation ---
   Deutliche Trennung von Navi und Contentbereich (angelehnt an Shopware 6
   Admin): Schatten am rechten Rand statt nur Farbkontrast. */
.cbm-sidebar {
    width: var(--cbm-sidebar-width);
    flex: 0 0 auto;
    background: var(--cbm-sidebar-bg);
    color: var(--cbm-sidebar-fg);
    display: flex;
    flex-direction: column;
    box-shadow: 3px 0 16px rgba(0, 0, 0, .4);
    transition: width .15s ease;
    /* KEIN eigener z-index hier auf allen Breiten - .cbm-sidebar IST
       gleichzeitig Bootstraps eigenes .offcanvas-Element (siehe
       "offcanvas-md offcanvas-start" in sidebar.twig). Ein pauschaler
       eigener z-index wuerde auch auf Mobile greifen und dort Bootstraps
       eigenen, viel hoeheren Offcanvas-z-index (--bs-zindex-offcanvas:
       1045) ueberschreiben - das Offcanvas-Backdrop (1040, unveraendert)
       laege dann VOR der ausgeklappten Navigation statt dahinter ("bg fade
       liegt ueber allem"). Ab Tablet-Breite (kein Offcanvas mehr, siehe
       .cbm-sidebar-Regel im Media-Query direkt darunter) bekommt sie einen
       eigenen, aber bewusst niedrigen z-index - siehe "Globale Ebenen
       (z-index)" oben am Dateianfang. */
}

/* WICHTIG: ohne eigene, vom Content unabhaengige Hoehe wuerde die Sidebar
   wegen align-items:stretch (Standard in .cbm-app) auf die Hoehe des
   Content-Bereichs mitwachsen (der z.B. bei einer langen Timeline/Doku-Seite
   deutlich hoeher als der Viewport werden kann) - dadurch war .cbm-sidebar__fixed
   nicht am Viewport-Rand "fixiert", sondern irgendwo am Ende dieser
   ueberlangen Sidebar. position:sticky + eigene Hoehe loest das: die Sidebar
   bleibt exakt Viewport-hoch und bleibt beim Scrollen der Seite oben kleben.
   NUR ab Tablet-Breite (wie beim Collapse-Toggle) - auf Mobile ist die
   Sidebar ohnehin schon per Bootstrap-Offcanvas position:fixed. */
@media (min-width: 768px) {
    .cbm-sidebar {
        position: sticky;
        top: 0;
        height: 100vh;
        z-index: 20;
    }
}

.cbm-sidebar__logo {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: 1rem 1.25rem;
    font-weight: 700;
    font-size: 1.05rem;
    color: #fff;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
    white-space: nowrap;
    overflow: hidden;
}

/* Logo-Icon: echtes <img> (brand('logo.svg'), siehe sidebar.twig) statt
   Inline-SVG, damit ein individuelles Logo per Datei-Tausch unter
   assets/img/custom/ funktioniert (App\Support\BrandAssets) - die
   mitgelieferte Datei hat bewusst fest codierte Marken-Farben, unabhaengig
   von App-Farbthemes in custom.css. Hier nur Layout. */
.cbm-sidebar__logo .cbm-logo-icon {
    flex: 0 0 auto;
    display: block;
}

.cbm-sidebar__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .75rem 1rem;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.cbm-lang-switch {
    display: flex;
}

.cbm-lang-btn {
    color: var(--cbm-sidebar-fg-muted);
    border: 1px solid transparent;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-size: .85rem;
    padding: .3rem .5rem;
}

.cbm-lang-btn:hover {
    color: #fff;
}

.cbm-sidebar__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: .5rem 0 1rem;
}

.cbm-auth-btn {
    color: var(--cbm-sidebar-fg);
    border: 1px solid rgba(255, 255, 255, .18);
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    font-size: .9rem;
}

.cbm-auth-btn:hover {
    color: #fff;
    border-color: rgba(255, 255, 255, .4);
}

.cbm-nav {
    flex: 1;
}

.cbm-nav-link {
    color: var(--cbm-sidebar-fg-muted);
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .65rem 1.25rem;
    border-left: 3px solid transparent;
    font-size: .95rem;
}

.cbm-nav-link i {
    font-size: 1.15rem;
    width: 1.4rem;
    text-align: center;
}

/* Jeder Navi-Punkt (inkl. Administration im festen unteren Bereich) bekommt
   eine eigene Icon-Farbe statt einheitlichem Grau - macht die Navi lebendiger
   und Punkte auf einen Blick unterscheidbar. Bleibt auch im aktiven/Hover-
   Zustand erhalten (nur Hintergrund/Textfarbe der Zeile aendern sich). */
.cbm-nav-link[data-target="calendar"] i { color: #4f46e5; }
.cbm-nav-link[data-target="timeline"] i { color: #0ea5e9; }
.cbm-nav-link[data-target="map"] i { color: #14b8a6; }
.cbm-nav-link[data-target="raeume"] i { color: #f59e0b; }
.cbm-nav-link[data-target="konflikte"] i { color: #ef4444; }
.cbm-nav-link[data-target="wlan"] i { color: #22c55e; }
.cbm-nav-link[data-target="checkin"] i { color: #06b6d4; }
.cbm-nav-link[data-target="doku"] i { color: #a78bfa; }
.cbm-nav-link[data-target="admin"] i { color: #ec4899; }

.cbm-nav-link:hover {
    color: #fff;
    background: rgba(255, 255, 255, .05);
}

.cbm-nav-link.active {
    color: #fff;
    background: color-mix(in srgb, var(--cbm-accent) 18%, transparent);
    border-left-color: var(--cbm-accent);
}

/* --- Fester unterer Sidebar-Bereich (Shopware-6-artig): Administration,
   Uhr, Ein-/Ausklapp-Toggle - bleibt beim Scrollen der Navi-Liste oben
   sichtbar, da er ausserhalb von .offcanvas-body liegt (siehe sidebar.twig). */
.cbm-sidebar__fixed {
    flex: 0 0 auto;
    background: var(--cbm-sidebar-bg-darker);
    border-top: 1px solid rgba(255, 255, 255, .08);
}

.cbm-sidebar__admin-link {
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.cbm-sidebar__clock {
    padding: .9rem 1.25rem;
    color: var(--cbm-sidebar-fg-muted);
    font-variant-numeric: tabular-nums;
}

.cbm-clock-time {
    font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 1.4rem;
    font-weight: 600;
    letter-spacing: .02em;
    background: linear-gradient(135deg, var(--cbm-brand-primary), var(--cbm-brand-secondary));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.cbm-clock-date {
    font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .72rem;
    letter-spacing: .05em;
    text-transform: uppercase;
    margin-top: .15rem;
}

/* Ein-/Ausklapp-Toggle: volle Breite als unterste Zeile der Sidebar (statt
   frei schwebend am Rand) - Shopware 6 Admin platziert ihn genauso. */
.cbm-sidebar-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    padding: .6rem;
    background: transparent;
    border: none;
    border-top: 1px solid rgba(255, 255, 255, .08);
    border-radius: 0;
    color: var(--cbm-sidebar-fg-muted);
}

.cbm-sidebar-toggle:hover {
    color: #fff;
    background: rgba(255, 255, 255, .05);
}

/* Tablet / mittlere Breiten: standardmaessig nur Icons - ausser der manuelle
   Toggle hat "ausgeklappt" erzwungen (.cbm-sidebar--force-expanded). */
@media (min-width: 768px) and (max-width: 1199.98px) {
    .cbm-sidebar:not(.cbm-sidebar--force-expanded) {
        width: var(--cbm-sidebar-width-icons);
    }

    .cbm-sidebar:not(.cbm-sidebar--force-expanded) .cbm-nav-label,
    .cbm-sidebar:not(.cbm-sidebar--force-expanded) .cbm-logo-label {
        display: none;
    }

    .cbm-sidebar:not(.cbm-sidebar--force-expanded) .cbm-nav-link {
        justify-content: center;
        padding: .75rem .25rem;
    }

    .cbm-sidebar:not(.cbm-sidebar--force-expanded) .cbm-auth-btn {
        justify-content: center;
        padding: .4rem;
    }

    /* Datum/Uhrzeit im Icon-Modus kompakt anzeigen */
    .cbm-sidebar:not(.cbm-sidebar--force-expanded) .cbm-sidebar__clock {
        text-align: center;
        padding: .75rem .25rem .25rem;
    }

    .cbm-sidebar:not(.cbm-sidebar--force-expanded) .cbm-clock-date {
        display: none;
    }

    .cbm-sidebar:not(.cbm-sidebar--force-expanded) .cbm-clock-time {
        font-size: .85rem;
    }
}

/* Manueller Ein-/Ausklapp-Toggle (wie Shopware 6 Admin): erzwingt Icon-only
   unabhaengig von der Fensterbreite, auch auf Desktop-Breiten. Zustand wird
   in app.js per localStorage gemerkt. */
.cbm-sidebar--force-collapsed {
    width: var(--cbm-sidebar-width-icons) !important;
}

.cbm-sidebar--force-collapsed .cbm-nav-label,
.cbm-sidebar--force-collapsed .cbm-logo-label {
    display: none;
}

.cbm-sidebar--force-collapsed .cbm-nav-link {
    justify-content: center;
    padding: .75rem .25rem;
}

.cbm-sidebar--force-collapsed .cbm-auth-btn,
.cbm-sidebar--force-collapsed .cbm-lang-btn {
    justify-content: center;
    padding: .4rem;
}

.cbm-sidebar--force-collapsed .cbm-sidebar__header {
    flex-direction: column;
    gap: .35rem;
}

.cbm-sidebar--force-collapsed .cbm-sidebar__clock {
    text-align: center;
    padding: .75rem .25rem .25rem;
}

.cbm-sidebar--force-collapsed .cbm-clock-date {
    font-size: .5rem; /* 8px */
}

.cbm-sidebar--force-collapsed .cbm-clock-time {
    font-size: .85rem;
}

/* Mobile: Sidebar wird zum Offcanvas (siehe offcanvas-md Klasse im Template).
   .cbm-sidebar__fixed liegt als Geschwister-Element NACH .offcanvas-body
   (das Bootstrap selbst scrollbar macht) - bleibt dadurch automatisch auch
   im ausgeklappten mobilen Layer unten fixiert, keine zusaetzliche Anpassung
   noetig. */
.cbm-burger {
    position: fixed;
    top: .6rem;
    left: .6rem;
    z-index: 1040; /* siehe "Globale Ebenen (z-index)" oben am Dateianfang -
                      identisch mit Bootstraps Offcanvas-Backdrop, das ist
                      hier unkritisch: sobald das Offcanvas offen ist, deckt
                      dessen eigener, hoeherer z-index (1045) sowohl Burger
                      als auch Backdrop ab. */
    background: var(--cbm-sidebar-bg);
    color: #fff;
    border-radius: .5rem;
    padding: .4rem .65rem;
}

/* --- Content ---
   Grund-Styling-Entscheidung: jede Ansicht (views/*.twig) hat GENAU einen
   Wurzel-Div, darin GENAU eine Card - das ist die verbindliche Grundstruktur
   fuer alle (Kalender/Timeline/Karte/Raeume/Konflikte/Administration; die
   Administration packt ihre mehreren Bereiche als Reiter EINER Card, siehe
   admin.twig). Ab Tablet-Breite bekommt diese eine Card die volle verfuegbare
   Hoehe und scrollt bei zu viel Inhalt NUR noch in ihrem eigenen card-body -
   die Seite/das Layout drumherum scrollt nie mit (siehe .cbm-app oben).
   min-height:0 ist an jeder Stelle dieser Flex-Kette noetig, sonst verhindert
   Flexbox' Default (min-height:auto) das Schrumpfen unter die Inhaltsgroesse
   und der Overflow "leckt" nach oben durch, statt lokal zu scrollen. */
.cbm-content {
    flex: 1;
    min-width: 0;
    padding: 1.5rem;
    background: #f4f6fa;
    /* KEIN eigener z-index/position hier (siehe "Globale Ebenen (z-index)"
       oben am Dateianfang): .cbm-content ist ein Flex-Item von .cbm-app -
       ein Flex-Item mit z-index != auto erzeugt per Spec einen eigenen
       Stacking-Context, auch OHNE position. Das wuerde jedes position:fixed-
       Element darin (z.B. .cbm-fab in der Kartenansicht) auf die lokale
       Ebene "1" einsperren, egal welchen z-index es selbst traegt - der
       Vergleich mit Geschwistern wie .cbm-sidebar (Ebene 20) faende dann
       schon EINE Ebene hoeher statt. Genau das fuehrte zu dem Bug, dass der
       fliegende Button zeitweise unsichtbar/verdeckt war. */
}

@media (min-width: 768px) {
    .cbm-content {
        height: 100vh;
        display: flex;
        flex-direction: column;
        /* Fallback fuer Seiten OHNE die Card-Struktur (freie content/*.twig-
           Seiten wie Doku/WLAN, die bewusst NICHT dieser Grundregel folgen,
           siehe Kommentar oben an .cbm-content) - normales Scrollen der
           gesamten Flaeche, damit z.B. eine lange Doku-Seite ueberhaupt
           erreichbar bleibt. Views MIT Card ueberschreiben das gleich
           darunter auf "nicht selbst scrollend". */
        overflow: auto;
    }

    /* :has() grenzt die "Buehne scrollt nie, nur die Card scrollt"-Regel
       gezielt auf Ansichten mit der verbindlichen Card-Struktur ein - ohne
       das wuerde z.B. die kartenlose Doku-Seite durch overflow:hidden
       ploetzlich unerreichbar. */
    .cbm-content:has(> div > .card) {
        overflow: hidden;
    }

    .cbm-content > div:has(> .card) {
        flex: 1;
        min-height: 0;
        display: flex;
        flex-direction: column;
    }

    .cbm-content > div > .card {
        flex: 1;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    .cbm-content > div > .card > .card-body {
        flex: 1;
        min-height: 0;
        overflow: auto;
    }
}

@media (max-width: 767.98px) {
    .cbm-content {
        padding-top: 3.5rem;
    }

    /* Kopfzeile (Toolbar/Subnavi) nach unten, Inhalt nach oben - .card ist
       bei Bootstrap grundsaetzlich (nicht erst ab Tablet-Breite) ein
       display:flex; flex-direction:column-Container, "order" reicht daher
       ohne weiteres Markup. Gilt fuer jede Ansicht mit der verbindlichen
       "eine Card"-Struktur (siehe .cbm-content-Kommentar weiter oben) -
       Kalender/Timeline/Karte/Räume/Konflikte/Administration gleichermassen.
       Der gesamte mobile Aufbau wird schrittweise weiter ueberarbeitet, das
       hier ist ein erster Schritt. */
    .cbm-content > div > .card > .card-header {
        order: 2;
    }

    .cbm-content > div > .card > .card-body {
        order: 1;
    }
}

/* --- Einheitliche Kopfzeilen-Toolbar ---
   EIN gemeinsames, flaches Klassen-Set fuer alle Card-Header mit Steuer-
   elementen statt pro Ansicht eigener Utility-Klassen/Groessen (Kalender/
   Timeline/Karte/Räume/Konflikte + die Admin-Subnavi) - siehe jeweilige
   *.twig. Struktur immer: .card-header.cbm-view-toolbar > .cbm-toolbar-start
   (Buttons/Titel, links) + optional .cbm-toolbar-end (rechts, z.B.
   "+"-Button). Custom content/*.twig-Seiten (Doku/WLAN) sind bewusst
   aussen vor. */
.cbm-view-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    flex-wrap: wrap;
    /* Feste Mindesthoehe statt sich rein aus dem Inhalt zu ergeben: Header
       mit echten Buttons (Kalender/Timeline) und reine Titel-Header (Räume/
       Konflikte, nur ein <span>) waeren sonst unterschiedlich hoch, weil ein
       Button durch sein eigenes Padding/Border mehr Platz braucht als
       reiner Text - card-header selbst hat ueberall dieselbe Polsterung.
       min-height sorgt dafuer, dass beide Header-Typen auf dieselbe
       Gesamthoehe kommen (Buttons definieren/ueberschreiten sie ohnehin von
       selbst, Text-Header werden ueber align-items:center einfach mittig
       darin zentriert). Werte passend zur Buttongroesse aus der
       Media-Query-Skala weiter unten. */
    min-height: 2rem;
}

@media (min-width: 768px) {
    .cbm-view-toolbar {
        min-height: 2.375rem;
    }
}

.cbm-toolbar-start,
.cbm-toolbar-end {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

/* Groesse der Steuerelemente folgt EINER Skala statt verstreuter
   .btn-sm-Klassen: auf Mobile einheitlich kompakt (bisher .btn-sm bei
   Kalender/Timeline) - greift auch auf Buttons OHNE eigene .btn-sm-Klasse
   (z.B. die per JS gerenderten Standort-Buttons der Kartenansicht, siehe
   map.js) sowie auf die Admin-Subnavi-Reiter (.nav-link), die von Haus aus
   groesser sind. */
@media (max-width: 767.98px) {
    .cbm-view-toolbar .btn {
        --bs-btn-padding-y: .25rem;
        --bs-btn-padding-x: .5rem;
        --bs-btn-font-size: .875rem;
    }

    .cbm-view-toolbar .nav-link {
        padding: .25rem .5rem;
        font-size: .875rem;
    }
}

/* Ab Tablet-Breite: einheitlich die groessere "Admin"-Groesse (Bootstraps
   Standard-Buttongroesse) - hebt ein vorhandenes .btn-sm wieder an, damit
   nicht mehr pro View einzeln zwischen .btn/.btn-sm entschieden werden muss. */
@media (min-width: 768px) {
    .cbm-view-toolbar .btn {
        --bs-btn-padding-y: .375rem;
        --bs-btn-padding-x: .75rem;
        --bs-btn-font-size: 1rem;
    }
}

/* --- Ampel-Böppel (Raum-Status) ---
   5 Zustaende, rein ueber data-color + CSS gestylt:
   - gruen        : heute UND morgen frei
   - rot          : heute UND morgen belegt
   - grau         : heute (admin-)blockiert / nicht buchbar
   - rot-gruen    : heute noch belegt, ab morgen frei (Checkout morgen)
   - gruen-rot    : heute noch frei, ab morgen belegt (Check-in morgen)
   Die beiden Uebergangs-Zustaende werden als weicher Gradient dargestellt. */
.cbm-ampel {
    display: inline-block;
    width: .85rem;
    height: .85rem;
    border-radius: 50%;
    background: var(--cbm-ampel-grau);
    vertical-align: middle;
    cursor: help;
}

.cbm-ampel[data-color="gruen"] { background: var(--cbm-ampel-gruen); }
.cbm-ampel[data-color="rot"] { background: var(--cbm-ampel-rot); }
.cbm-ampel[data-color="grau"] { background: var(--cbm-ampel-grau); }

.cbm-ampel[data-color="rot-gruen"] {
    background: linear-gradient(135deg,
        var(--cbm-ampel-rot) 0%, var(--cbm-ampel-rot) 45%,
        var(--cbm-ampel-gruen) 55%, var(--cbm-ampel-gruen) 100%);
}

.cbm-ampel[data-color="gruen-rot"] {
    background: linear-gradient(135deg,
        var(--cbm-ampel-gruen) 0%, var(--cbm-ampel-gruen) 45%,
        var(--cbm-ampel-rot) 55%, var(--cbm-ampel-rot) 100%);
}

/* --- Administration: sortierbare Spalten + Name-Klick-Bearbeiten --- */
.cbm-raum-name-cell {
    cursor: pointer;
}

.cbm-raum-name-cell:hover {
    text-decoration: underline;
}

.cbm-sortable-table .cbm-sort-th {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.cbm-sortable-table .cbm-sort-th:hover {
    color: var(--cbm-accent);
}

.cbm-sort-icon {
    font-size: .65rem;
}

/* --- Öffentliche Räume-Übersicht --- */
.cbm-raeume-row {
    cursor: pointer;
}

/* --- Raum-Modal --- */
.cbm-room-photo {
    max-height: 13.75rem; /* 220px */
    max-width: 100%;
    border-radius: .5rem;
    object-fit: cover;
}

.cbm-booking-list {
    max-height: 16.25rem; /* 260px */
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: .5rem;
    /* Unten etwas Luft fuer die Pfeilspitze des aktiven Badges (siehe
       .cbm-booking-badge--active::after) - sonst wirkt sie am unteren Rand
       der scrollbaren Liste abgeschnitten/gequetscht. */
    padding: 0 .25rem .625rem 0;
}

.cbm-booking-badge {
    position: relative;
    cursor: pointer;
    font-size: .85rem;
    padding: .5rem .75rem;
    color: #fff;
    border: 2px solid transparent;
    transition: transform .1s ease, border-color .15s ease, opacity .15s ease;
}

/* Sobald IRGENDEIN Badge aktiv ist, alle anderen dezent zuruecknehmen -
   macht die Auswahl auch bei vielen/mehrzeiligen Badges auf den ersten
   Blick eindeutig. Klasse sitzt auf .cbm-booking-list selbst (statt jedes
   Badge einzeln zu pruefen), siehe renderBookingBadges() in room-modal.js. */
.cbm-booking-list--has-active .cbm-booking-badge:not(.cbm-booking-badge--active) {
    opacity: .45;
}

/* Aktuell im Detailformular darunter angezeigte Buchung - der kleine Zeiger
   (::after) haengt direkt an DIESEM Badge (nicht mehr an einem gemeinsamen
   Element unterhalb der ganzen Liste, siehe Doku-Kommentar hier: bei
   mehrzeiligen Badges - z.B. mobil schon ab 2 Buchungen - liess sich eine
   einzelne, nur X-positionierte Zeiger-Spitze nicht mehr eindeutig einer
   Zeile zuordnen. Als ::after des jeweiligen Badges braucht es dafuer auch
   keinerlei JS-Positionsberechnung/getBoundingClientRect() mehr - der
   Browser haengt es automatisch an die richtige Stelle, in jeder Zeile). */
.cbm-booking-badge--active {
    border-color: #1b2331;
    transform: translateY(-1px);
    opacity: 1;
}

.cbm-booking-badge--active::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -.625rem; /* 10px */
    transform: translateX(-50%);
    width: 0;
    height: 0;
    border-left: .5rem solid transparent;
    border-right: .5rem solid transparent;
    border-top: .5rem solid var(--cbm-badge-color, #1b2331);
    pointer-events: none;
}

.cbm-booking-badge__icon {
    margin-right: .3rem;
}

/* Detailformular-Container: braucht position:relative als Bezugsrahmen fuer
   den fliegenden Bearbeiten-Button (siehe .cbm-detail-edit-fab). */
.cbm-booking-detail {
    position: relative;
}

.cbm-detail-edit-fab {
    position: absolute;
    top: .5rem;
    right: .5rem;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}

/* --- Konflikte-Uebersicht --- */
.cbm-konflikt-item {
    cursor: pointer;
}

/* --- Kalenderansicht: Tages-Böppel pro Raum --- */
.cbm-cal-chip {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    color: #fff;
    font-size: .65rem;
    font-weight: 700;
    margin: .1rem;
    cursor: pointer;
}

/* Komplett abgeschlossene Buchung (end_date in der Vergangenheit, siehe
   calendar.js/timeline.js) - optisch zurueckgenommen, aber weiterhin normal
   anklickbar (oeffnet die Bearbeiten-Maske, siehe eventClick()/room-modal.js). */
.cbm-cal-chip--past {
    opacity: .4;
}

/* Ueberschneidung mit einer anderen Buchung im selben Raum (siehe "Konflikte") */
.cbm-cal-chip--conflict {
    box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px #dc3545;
}

.cbm-cal-chip--conflict::after {
    content: "!";
    position: absolute;
    top: -.25rem; /* -4px */
    right: -.25rem; /* -4px */
    width: .75rem; /* 12px */
    height: .75rem; /* 12px */
    border-radius: 50%;
    background: #dc3545;
    color: #fff;
    font-size: .5625rem; /* 9px */
    font-weight: 700;
    line-height: .75rem; /* 12px */
    text-align: center;
}

/* Halber Böppel am Checkin-/Checkout-Tag einer mehrtaegigen Buchung (ohne
   Kuerzel-Text - zu klein dafuer): Checkin = rechte Haelfte gefuellt
   (Ankunft nachmittags), Checkout = linke Haelfte (Abreise vormittags) -
   dieselbe Links/Rechts-Logik wie die Halbtag-Balken in der Timeline. */
.cbm-cal-chip--half {
    background: transparent;
}

.cbm-cal-chip--half::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--cbm-chip-color, #9aa0a8);
}

.cbm-cal-chip--checkin::before {
    clip-path: inset(0 0 0 50%);
}

.cbm-cal-chip--checkout::before {
    clip-path: inset(0 50% 0 0);
}

/* Hover auf einen Böppel markiert den gesamten zusammenhaengenden
   Buchungszeitraum im sichtbaren Kalender (siehe highlightBookingRange()
   in calendar.js) - Farbe kommt vom jeweiligen Raum. */
.cbm-cal-day--highlight {
    background: color-mix(in srgb, var(--cbm-highlight-color, var(--cbm-brand-primary)) 18%, transparent);
}

/* --- Kalenderansicht: "+"-Button pro Tageszelle (neue Buchung) --- */
.cbm-cal-add-btn {
    position: absolute;
    bottom: .125rem; /* 2px */
    right: .125rem; /* 2px */
    width: 1.3rem;
    height: 1.3rem;
    padding: 0;
    line-height: 1;
    font-size: .65rem;
    border: 1px solid #dde2ea;
    border-radius: .3rem;
    background: #fff;
    color: #9aa4b6;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.cbm-cal-add-btn:hover {
    background: var(--cbm-accent);
    border-color: var(--cbm-accent);
    color: #fff;
}

/* --- Modal-Header: Speichern-Icon vor dem Schliessen-Kreuz (siehe
   new_booking_modal.twig, room_modal.twig, admin.twig) - einheitlich in
   allen Modals mit Formular verfuegbar. */
.cbm-modal-save-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border-radius: .375rem;
}

/* Bestaetigungs-Dialoge (Loeschen-Bestaetigung, Dangerzone), die IMMER aus
   einem bereits offenen Basis-Modal heraus geoeffnet werden koennen (z.B.
   Buchung-Loeschen aus dem Raum-Modal) - Bootstrap kennt von Haus aus keine
   gestapelten Modals (alle .modal/.modal-backdrop teilen denselben
   z-index), deshalb hier eine explizite Ebene hoeher. Siehe "Globale Ebenen
   (z-index)" oben am Dateianfang; das Backdrop bekommt seine Klasse per JS
   zugewiesen (siehe elevateStackedModal() in app.js), weil Bootstrap dessen
   DOM-Element selbst erzeugt und keine eigene ID/Klasse dafuer anbietet. */
#cbmConfirmModal,
#cbmDangerConfirmModal {
    z-index: 1075;
}

.cbm-modal-stacked-backdrop {
    z-index: 1070;
}

/* --- Tabellen-Timeline ---
   Bewusst KEIN position:sticky fuer die Raumnamen-Spalte (siehe Kommentar
   in timeline.twig) - stattdessen zwei physisch getrennte Bereiche: ein
   fixer, nicht scrollender Namensblock links + ein horizontal scrollender
   Tages-Raster rechts. Beide bekommen pro Zeile exakt dieselbe Hoehe
   (--cbm-tl-row-h), dadurch bleiben sie ohne jeden JS-Sync exakt aufeinander
   ausgerichtet. */
:root {
    --cbm-tl-name-col: 11.25rem; /* 180px */
    --cbm-tl-day-col: 3.5rem; /* 56px */
    --cbm-tl-row-h: 2.75rem; /* 44px */
}

.cbm-tl-outer {
    display: flex;
    align-items: flex-start;
}

.cbm-tl-names {
    flex: 0 0 var(--cbm-tl-name-col);
    width: var(--cbm-tl-name-col);
    border-right: 2px solid #dde2ea;
}

.cbm-tl-wrap {
    flex: 1;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
}

.cbm-tl-grid {
    display: grid;
    grid-template-columns: repeat(var(--cbm-tl-days, 1), var(--cbm-tl-day-col));
    grid-auto-rows: var(--cbm-tl-row-h);
}

.cbm-tl-cell {
    height: var(--cbm-tl-row-h);
    border-bottom: 1px solid #edf0f5;
    border-right: 1px solid #edf0f5;
    display: flex;
    align-items: center;
    padding: 0 .4rem;
    font-size: .78rem;
    color: #6c7688;
    box-sizing: border-box;
}

.cbm-tl-header {
    background: #fff;
    font-weight: 600;
    justify-content: center;
    text-align: center;
    flex-direction: column;
    line-height: 1.1;
}

.cbm-tl-room {
    background: #fff;
    cursor: pointer;
    gap: .4rem;
    font-size: .85rem;
    color: #1b2331;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Raumname-Text - font-size bewusst auf 1rem angehoben (statt der von
   .cbm-tl-room geerbten .85rem): soll ueberall dort, wo ein Raumname
   auftaucht (Räume-Übersicht, Administration, hier), GLEICH aussehen - der
   jeweils groesste der drei Werte gewinnt. Normale Schriftfarbe/-staerke
   (nicht mehr in Raumfarbe eingefaerbt/fett) - die Raumfarbe steckt jetzt im
   Kürzel-Böppel davor (.cbm-tl-room-chip), Text soll konsistent bleiben. */
.cbm-tl-room-name {
    font-size: 1rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Kuerzel-Böppel im selben Look wie die Kalender-Belegungsböppel
   (.cbm-cal-chip, siehe app.css/calendar.js) - immer sichtbar, VOR dem Namen
   (einheitlicher Aufbau wie Räume-Übersicht/Administration: Böppel + Name +
   (Standort) + Ampel). Auf Mobile bleibt NUR er stehen, siehe Media-Query
   unten (.cbm-tl-room-name wird dort ausgeblendet). */
.cbm-tl-room-chip {
    flex-shrink: 0;
}

.cbm-tl-corner {
    background: #fff;
    border-right: none;
}

@media (max-width: 767.98px) {
    :root {
        /* Schmale Namensspalte auf Mobile: nur noch Kuerzel-Böppel + Ampel
           statt vollem Raumnamen (siehe .cbm-tl-room-name/.cbm-tl-room-chip
           oben) - der gesamte mobile Aufbau wird schrittweise ueberarbeitet,
           das hier ist der erste Schritt fuer die Timeline. */
        --cbm-tl-name-col: 3.75rem; /* 60px */
    }

    .cbm-tl-room {
        justify-content: center;
        padding: 0 .2rem;
    }

    .cbm-tl-room-name {
        display: none;
    }
}

.cbm-tl-bar {
    align-self: center;
    margin: 0 .125rem; /* 2px */
    height: 1.625rem; /* 26px */
    border-radius: .35rem;
    background: var(--cbm-accent);
    color: #fff;
    font-size: .72rem;
    display: flex;
    align-items: center;
    padding: 0 .4rem;
    overflow: hidden;
    white-space: nowrap;
    cursor: pointer;
}

.cbm-tl-bar.cbm-tl-bar--blocked {
    background: var(--cbm-ampel-grau);
}

/* Komplett abgeschlossene Buchung (end_date in der Vergangenheit, siehe
   timeline.js) - optisch zurueckgenommen, aber weiterhin normal anklickbar
   (oeffnet die Bearbeiten-Maske, siehe room-modal.js). */
.cbm-tl-bar.cbm-tl-bar--past {
    opacity: .4;
}

/* Ueberschneidung mit einer anderen Buchung im selben Raum (siehe "Konflikte"):
   roter Rahmen + halbe Zeilenhoehe, oben/unten gestapelt (Spur 0/1, siehe
   timeline.js laneAssignment()) - so bleiben beide ueberschneidenden Balken
   sichtbar statt sich gegenseitig zu verdecken. */
.cbm-tl-bar.cbm-tl-bar--conflict {
    outline: 2px solid #dc3545;
    align-self: stretch;
}

.cbm-tl-bar--conflict.cbm-tl-bar--lane0 {
    align-self: start;
}

.cbm-tl-bar--conflict.cbm-tl-bar--lane1 {
    align-self: end;
}

/* Markierung der heutigen Spalte ueber alle Raumzeilen (inkl. Kopfzeile)
   hinweg - dieselbe hellgelbe Farbe wie im Kalender (--cbm-today-bg-color),
   damit beide Ansichten "aus einem Guss" wirken. */
.cbm-tl-today-marker {
    background: var(--cbm-today-bg-color);
    pointer-events: none;
}

/* FullCalendars eingebaute Toolbar ist deaktiviert (headerToolbar: false in
   calendar.js) - die Kopfzeile in calendar.twig ist stattdessen 1:1 wie die
   Timeline aus echten Bootstrap-Buttons aufgebaut (gleiche Klassen), braucht
   also keine eigenen Overrides mehr. Denselben hellgelben "heute"-Ton wie in
   der Timeline verwenden (statt FullCalendars eigenem Default). */
.fc {
    --fc-today-bg-color: var(--cbm-today-bg-color);
}

/* --- SVG-Kartenansicht --- */
.cbm-map-wrap {
    width: 100%;
    overflow: auto;
}

.cbm-map-svg {
    width: 100%;
    max-width: 56.25rem; /* 900px */
    height: auto;
    max-height: 75vh;
}

.cbm-map-room rect {
    transition: opacity .15s ease;
    cursor: pointer;
}

.cbm-map-room:hover rect {
    opacity: .85;
}

.cbm-map-room text {
    fill: #fff;
    font-size: 15px;
    font-weight: 700;
    pointer-events: none;
}

.cbm-placeholder-view {
    background: #fff;
    border: 1px dashed #d7dce5;
    border-radius: .75rem;
    padding: 3rem 1.5rem;
    text-align: center;
    color: #6c7688;
}

/* Fliegender runder "+"-Button unten rechts (aktuell nur Kartenansicht) -
   gleicher Farbverlauf wie Logo/Uhr, damit er als Marken-Akzent erkennbar
   bleibt statt als generischer Bootstrap-Button. position: fixed statt
   absolute, damit er beim Scrollen der Kartenansicht sichtbar bleibt;
   z-index unter Bootstraps Modal-Backdrop (>=1050), damit er von Modals
   ueberdeckt wird statt darueber zu schweben (siehe "Globale Ebenen
   (z-index)" oben am Dateianfang). Liegt als Kind von .cbm-content im DOM -
   funktioniert nur korrekt, WEIL .cbm-content selbst keinen eigenen
   z-index/Stacking-Context mehr hat (sonst waere dieser Wert hier wirkungslos
   eingesperrt, siehe Kommentar an .cbm-content). */
.cbm-fab {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    width: 3.5rem;
    height: 3.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--cbm-brand-primary), var(--cbm-brand-secondary));
    color: #fff;
    font-size: 1.5rem;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .25);
    z-index: 1030;
    transition: transform .15s ease, box-shadow .15s ease;
}

.cbm-fab:hover {
    color: #fff;
    transform: scale(1.06);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .3);
}

.cbm-fab:active {
    transform: scale(.96);
}

/* --- Scrollbars: schlank, app-artig, moeglichst plattform-/browser-
   einheitlich. Firefox nutzt die standardisierten scrollbar-*-Properties,
   WebKit/Blink (Chrome/Edge/Safari) nur die praefixierten ::-webkit-scrollbar-
   Pseudo-Elemente - es braucht beide, es gibt (Stand 2026) keine einzelne
   Eigenschaft, die auf allen Browsern gleich funktioniert. */
* {
    scrollbar-width: thin;
    scrollbar-color: #c1c7d0 transparent;
}

::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background-color: #c1c7d0;
    border-radius: 999px;
    border: 2px solid transparent;
    background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
    background-color: #9aa3b1;
}

/* --- Splashscreen (siehe layout.twig) ---
   Typische App-Splash-Optik: sehr helles Grau, grosses zentriertes Logo,
   darunter ein kleiner, dezenter "Powered by"-Hinweis in dunklerem Grau -
   NICHT das Marken-Indigo/Pink fuer den Text, nur das kleine Icon bleibt
   farbig. Blendet per JS (layout.twig) kurz nach dem Laden aus. */
.cbm-splash {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.75rem;
    background: #f7f7f9;
    transition: opacity .4s ease;
}

.cbm-splash--hidden {
    opacity: 0;
    pointer-events: none;
}

.cbm-splash__logo {
    width: 9.25rem; /* 148px */
    height: 9.25rem; /* 148px */
}

.cbm-splash__powered {
    display: flex;
    align-items: center;
    gap: .5rem;
    color: #6c7280;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .01em;
}

.cbm-splash__powered img {
    width: 1.125rem; /* 18px */
    height: 1.125rem; /* 18px */
    flex-shrink: 0;
}

/* --- Site-Gate-Login (siehe gate_login.twig/App\Auth\SiteGate) ---
   Bewusst dieselbe Optik wie der Splashscreen oben - beide sind die
   "Basis-Identitaet" der Plattform, das Splash ist quasi diese Seite MINUS
   Formular. Login ist aber die komplette eigenstaendige Seite (nicht wie
   .cbm-splash ein Overlay ueber der ladenden App dahinter) - deshalb
   min-height statt position:fixed+inset. Die Powered-by-Zeile bleibt
   .cbm-splash__powered (1:1 wiederverwendet), nur die Positionierung
   (fix nahe der unteren Browserkante statt Teil der zentrierten Gruppe)
   kommt vom umschliessenden .cbm-gatepage__powered hier. */
.cbm-gatepage {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.75rem;
    background: #f7f7f9;
    padding: 2rem 1rem;
}

.cbm-gatepage__logo {
    width: 9.25rem; /* wie .cbm-splash__logo, 148px */
    height: 9.25rem;
}

.cbm-gatepage__form {
    width: 100%;
    max-width: 20rem;
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
}

/* Bewusst kein Bootstrap .form-control - "nur eine Unterlinie" statt der
   sonst app-weiten Input-Box, fuer die typische minimalistische
   Basis-Login-Optik. */
.cbm-gate-input {
    width: 100%;
    border: 0;
    border-bottom: 1px solid #d7dce5;
    border-radius: 0;
    background: transparent;
    padding: .5rem .25rem;
    font-size: 1rem;
    color: #1b2331;
    transition: border-color .15s ease;
}

.cbm-gate-input:focus {
    outline: none;
    box-shadow: none;
    border-bottom-color: #4f46e5;
}

.cbm-gate-input::placeholder {
    color: #9aa4b6;
}

.cbm-gate-forgot {
    display: block;
    text-align: right;
    margin-top: -.4rem;
    font-size: .78rem;
    color: #6c7688;
    text-decoration: none;
}

.cbm-gate-forgot:hover {
    color: #4f46e5;
    text-decoration: underline;
}

.cbm-gate-error {
    font-size: .85rem;
    color: #dc3545;
}

.cbm-gate-submit {
    width: 100%;
}

.cbm-gatepage__powered {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 1.25rem;
    display: flex;
    justify-content: center;
}

/* --- Nicht verlinkte Dev-Werkzeuge (siehe assets/js/dev-tools.js) ---
   Baut sein komplettes Markup per JS auf, deshalb hier nur generisches
   Overlay-Styling - keine eigenen IDs/Feinheiten noetig. Bewusst simple
   Klick-auf-Backdrop-schliesst-Logik statt Bootstrap-Modal (dev-tools.js
   soll unveraendert auf jeder Seite funktionieren, auch dem Site-Gate-Login
   OHNE Bootstrap-JS-Bundle). */
.cbm-devtools {
    position: fixed;
    inset: 0;
    z-index: 2100;
    background: rgba(27, 35, 49, .55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.cbm-devtools__box {
    position: relative;
    background: #fff;
    border-radius: .5rem;
    box-shadow: 0 12px 40px rgba(0, 0, 0, .3);
    padding: 1.5rem;
    width: 100%;
    max-width: 32rem;
    max-height: 90vh;
    overflow: auto;
}

.cbm-devtools__close {
    position: absolute;
    top: .75rem;
    right: .75rem;
}
