/*
 * Only what neither Bootstrap nor gg-design covers. Colours, themes, the
 * crest, the backgrounds, the login card and the display font come from the
 * shared gg-design WebJar (/webjars/gg-design/css/gg-design.css, loaded
 * before this file) so ISB looks like UTINNI rather than developing a
 * private design language.
 */

.card-header {
    font-weight: 600;
}

/* Permission names are identifiers — keep them readable and unwrapped. */
code.badge {
    font-family: var(--bs-font-monospace);
    font-weight: 400;
    letter-spacing: 0.01em;
}

dl.row dt {
    font-weight: 500;
    color: var(--bs-secondary-color);
}

dl.row dd {
    margin-bottom: 0.5rem;
}

/* Long identifiers (role names, group names) must not force a horizontal
   scrollbar on narrow screens. */
.text-break-anywhere {
    overflow-wrap: anywhere;
}

/*
 * Die Punkte einer Gruppe in der Navigationsleiste — „Personen & Rechte“,
 * „Einstellungen“.
 *
 * Geöffnet wird das von Vue, nicht von Bootstraps Dropdown-JS: der aufgeklappte
 * Zustand richtet sich nach der Adresse, und ein Tipp auf den Burger darf es
 * nicht sofort wieder zuklappen (Bootstrap zählt das als Klick daneben). Ohne
 * Popper setzt Bootstrap `top`/`left` nicht — das passiert nur über
 * `[data-bs-popper]` —, deshalb steht die Lage hier. `left: 0` bezieht sich auf
 * den Eintrag, nicht auf die Leiste: jede Gruppe klappt unter sich selbst auf.
 */
@media (min-width: 992px) {
    .navbar .isb-submenu {
        top: 100%;
        left: 0;
        margin-top: 0.25rem;
        min-width: 15rem;
    }
}

/*
 * Unter lg stecken die Gruppen im Burger-Menü. Dort sollen ihre Punkte keine
 * eigene Karte über der Navigationsleiste sein, sondern eine eingerückte Liste
 * darin.
 */
@media (max-width: 991.98px) {
    .navbar .isb-submenu {
        border: 0;
        box-shadow: none;
        background-color: transparent;
        margin-left: 0.75rem;
        padding-left: 0.75rem;
        border-left: 2px solid var(--bs-border-color);
    }

    /* Fingerbreite Ziele; Bootstraps Vorgabe ist für die Maus gedacht. */
    .navbar .isb-submenu .dropdown-item,
    .navbar .navbar-nav .nav-link {
        min-height: 2.75rem;
    }

    /* Vier Einträge samt der aufgeklappten Gruppe passen auf einem kleinen
       Handy nicht ins Bild. */
    .navbar .navbar-collapse {
        max-height: calc(100vh - 5.5rem);
        overflow-y: auto;
    }
}

/*
 * Der Punkt, auf dem man steht. Bewusst nicht über die Primärfarbe markiert:
 * gg-designs helles Blau trägt keine helle Schrift (2,1:1). Fette Schrift,
 * ein Balken und aria-current sagen es statt dessen — und nicht allein über
 * die Farbe.
 */
.isb-submenu .dropdown-item.isb-current {
    background-color: var(--bs-secondary-bg);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--bs-primary);
}

.isb-submenu .dropdown-item:focus-visible {
    outline: 2px solid var(--bs-dark);
    outline-offset: -2px;
}

/* The spam trap of /register: out of sight and out of the tab order, but
   still in the form for bots that fill in every field. Not display:none,
   which some bots skip. */
.isb-trap {
    position: absolute;
    left: -10000px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/*
 * Der Regeltext über dem Registrierungsformular. Rund 20 000 Zeichen — ohne
 * eigenen Scrollbereich stünde das Formular zwei Bildschirmseiten weiter
 * unten. Der Kasten ist mit der Tastatur erreichbar (tabindex) und behält
 * seinen Rahmen, damit sichtbar bleibt, dass darin noch etwas steht.
 *
 * Das Markup darin kommt aus dem Markdown-Renderer und besteht nur aus
 * Absätzen, Listen, Hervorhebungen und Links; mehr muss hier nicht gestaltet
 * werden.
 */
.isb-rules {
    max-height: 24rem;
    overflow-y: auto;
    padding: 0.75rem 1rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background-color: var(--bs-body-bg);
    font-size: 0.9375rem;
}

.isb-rules > :last-child {
    margin-bottom: 0;
}

.isb-rules:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

/*
 * Das Overlay der Administration (`<isb-overlay>`, spa-modules/_global/overlay.js).
 * Warum von Hand und nicht mit Bootstraps Modal, steht dort; hier steht nur,
 * was das Aussehen betrifft.
 *
 * Die z-Ebene liegt auf Bootstraps Modal-Höhe (1055), also über der fest
 * stehenden Navigationsleiste (1030). Toasts und Tooltips bleiben darüber.
 */
.isb-overlay {
    position: fixed;
    inset: 0;
    z-index: 1055;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background-color: rgba(0, 0, 0, 0.5);
}

/*
 * Kopf und Fuß stehen, der Inhalt rollt: eine Gruppe mit 200 Mitgliedern soll
 * den Dialog nicht über den Bildschirmrand hinausschieben, und „Speichern“
 * soll dabei sichtbar bleiben.
 */
.isb-overlay-dialog {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-height: 100%;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.35);
    animation: isb-overlay-in 0.12s ease-out;
}

.isb-overlay-md { max-width: 32rem; }
.isb-overlay-lg { max-width: 50rem; }
.isb-overlay-xl { max-width: 68rem; }

.isb-overlay-header,
.isb-overlay-footer {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
}

.isb-overlay-header {
    justify-content: space-between;
    border-bottom: 1px solid var(--bs-border-color);
}

.isb-overlay-footer {
    flex-wrap: wrap;
    justify-content: flex-end;
    border-top: 1px solid var(--bs-border-color);
    background-color: var(--bs-tertiary-bg);
    border-radius: 0 0 var(--bs-border-radius-lg) var(--bs-border-radius-lg);
}

.isb-overlay-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem;
}

/*
 * Der Rollbereich bekommt beim Öffnen den Fokus, damit er sich mit den
 * Pfeiltasten rollen lässt. Mit der Tastatur ist er nicht erreichbar
 * (tabindex="-1"), deshalb darf der Rahmen hier weg — jedes Bedienelement
 * darin behält seinen eigenen.
 */
.isb-overlay-body:focus {
    outline: none;
}

/*
 * Bei 200 Mitgliedern rollt die Kopfzeile der Tabelle sonst als Erstes aus dem
 * Bild, und ab da rät man, welche Spalte der Zeitraum war. Der Rahmen kommt als
 * `box-shadow`: Bootstraps Reboot setzt `border-collapse: collapse`, und dabei
 * bleibt ein echter Rahmen beim Rollen zurück.
 */
.isb-overlay-body .table > thead {
    position: sticky;
    top: -1rem;
    z-index: 1;
    background-color: var(--bs-body-bg);
}

.isb-overlay-body .table > thead th {
    background-color: var(--bs-body-bg);
    box-shadow: inset 0 -1px 0 var(--bs-border-color);
}

/* Was etwas wegnimmt, sieht man am Dialog, nicht erst am Knopf darin. */
.isb-overlay-danger {
    border-color: var(--bs-danger-border-subtle);
}

.isb-overlay-danger .isb-overlay-header {
    background-color: var(--bs-danger-bg-subtle);
    border-bottom-color: var(--bs-danger-border-subtle);
    border-radius: var(--bs-border-radius-lg) var(--bs-border-radius-lg) 0 0;
}

body.isb-overlay-open {
    overflow: hidden;
}

@keyframes isb-overlay-in {
    from { opacity: 0; transform: translateY(0.5rem); }
    to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .isb-overlay-dialog {
        animation: none;
    }
}

/*
 * Auf dem Handy nimmt der Dialog den ganzen Bildschirm: bei 375 px Breite wäre
 * ein zentrierter Kasten mit Rand ringsum nur noch eine Spalte. Das Kreuz ist
 * hier fingerbreit, wie die übrigen Schalter unter lg.
 */
@media (max-width: 575.98px) {
    .isb-overlay {
        padding: 0;
    }

    .isb-overlay-dialog {
        max-width: none;
        height: 100%;
        border: 0;
        border-radius: 0;
    }

    .isb-overlay-footer {
        border-radius: 0;
    }
}

@media (max-width: 991.98px) {
    .isb-overlay-header .btn-close {
        width: 2.75rem;
        height: 2.75rem;
        background-size: 1rem;
    }
}

/*
 * Der Spinner: das Wappen als Münze (spa-modules/_global/spinner.js).
 *
 * Eine volle Drehung um die senkrechte Achse ist genau die gewünschte Folge —
 * schmaler bis zur Kante, gespiegelt breiter, wieder schmaler, richtig herum
 * breiter. Linear, weil eine Münze nicht abbremst; die scheinbare Beschleunigung
 * an der Kante liefert der Kosinus der Drehung von selbst. Die Perspektive
 * steckt in der Transformation statt am Elternelement, damit das Bild in jedem
 * Behälter gleich aussieht. Das Abdunkeln zur Kante hin ist das Licht, das
 * über eine schräg stehende Metallfläche wandert.
 */
.isb-spinner {
    --isb-coin-size: 3rem;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
}

.isb-spinner-sm {
    --isb-coin-size: 1.25rem;
    flex-direction: row;
    gap: 0.5rem;
    vertical-align: middle;
}

.isb-spinner-lg {
    --isb-coin-size: 6rem;
}

.isb-spinner-coin {
    width: var(--isb-coin-size);
    height: var(--isb-coin-size);
    border-radius: 50%;
    animation: isb-coin-flip 1.6s linear infinite;
}

.isb-spinner-label {
    color: var(--bs-secondary-color);
}

/*
 * Im Knopf gilt die Farbe des Knopfs. Das gedämpfte Grau ist für eine
 * wartende Fläche gedacht; auf btn-primary oder btn-danger stünde damit
 * grauer Text auf farbigem Grund, und ausgerechnet die Beschriftung, die
 * sagt was läuft, wäre die am schlechtesten lesbare Stelle der Seite.
 */
.btn .isb-spinner-label {
    color: inherit;
}

@keyframes isb-coin-flip {
    0% {
        transform: perspective(calc(var(--isb-coin-size) * 4)) rotateY(0deg);
        filter: brightness(1);
    }
    25% {
        transform: perspective(calc(var(--isb-coin-size) * 4)) rotateY(90deg);
        filter: brightness(0.6);
    }
    50% {
        transform: perspective(calc(var(--isb-coin-size) * 4)) rotateY(180deg);
        filter: brightness(1);
    }
    75% {
        transform: perspective(calc(var(--isb-coin-size) * 4)) rotateY(270deg);
        filter: brightness(0.6);
    }
    100% {
        transform: perspective(calc(var(--isb-coin-size) * 4)) rotateY(360deg);
        filter: brightness(1);
    }
}

/* Wer Bewegung abgeschaltet hat, bekommt ein ruhiges Pulsieren statt der Drehung. */
@media (prefers-reduced-motion: reduce) {
    .isb-spinner-coin {
        animation: isb-coin-pulse 2s ease-in-out infinite;
    }
}

@keyframes isb-coin-pulse {
    50% {
        opacity: 0.5;
    }
}
