/*
 * Das blaue Backend.
 *
 * `modules/_display_layouts.css` ist dasselbe Modul, aus dem am Gerät die Bühne ihre Grid-Spuren
 * bekommt. Es hier zu importieren ist der ganze Trick hinter der Layoutauswahl: die Miniatur ist
 * kein Bild der Aufteilung, sie *ist* die Aufteilung im Kleinen — eine Miniatur, die etwas
 * anderes zeigt als der Bildschirm im Rathaus, ist damit strukturell unmöglich.
 *
 * `modules/_surface_roles.css` ist aus demselben Grund geteilt: die Farbtupfer der Flächenwahl
 * im Display-Editor nehmen ihre Farbe aus derselben Property wie der Bereich am Gerät.
 *
 * `@import` gehört an den Kopf der Datei: nach der ersten Regel ist er nach Spezifikation
 * ungültig und der Browser verwirft ihn stillschweigend.
 */
@import "modules/_display_layouts--XVxQ_L.css";
@import "modules/_surface_roles-p_KniFZ.css";

body {
    background: #f0f2f5;
}

.login-card {
    max-width: 420px;
}

.mandant-header {
    background: #1e293b;
    color: #fff;
    border-radius: 0.75rem 0.75rem 0 0;
    padding: 1.5rem 2rem 1.25rem;
}

.mandant-header .mandant-name {
    font-size: 1.1rem;
    font-weight: 700;
}

.mandant-header .mandant-sub {
    font-size: 0.8rem;
    color: #94a3b8;
    margin-top: 0.2rem;
}

body {
    background: #f0f2f5;
}

.sidebar {
    --sidebar-bg: #1e293b;
    /* Keeps the drawer as wide as the docked sidebar; Bootstrap defaults to 400px. */
    --bs-offcanvas-width: 260px;

    width: 260px;
    background: var(--sidebar-bg);
    color: #cbd5e1;
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    overflow-y: auto;
}

/* Docked from lg up. Below that `.offcanvas-lg` positions the sidebar as a
   drawer, which `position: sticky` here would override. */
@media (min-width: 992px) {
    .sidebar {
        position: sticky;
        top: 0;
        height: 100vh;
        min-height: 100vh;
        /* `.offcanvas-lg` forces `background-color: transparent !important` from
           lg up, so the docked sidebar has to answer in kind to stay dark. */
        background-color: var(--sidebar-bg) !important;
    }
}
.sidebar-brand {
    padding: 1.25rem 1rem;
    border-bottom: 1px solid #334155;
}
.sidebar-brand .brand-name {
    font-weight: 700;
    color: #f1f5f9;
    font-size: 1rem;
}
.sidebar-brand .brand-sub {
    font-size: 0.75rem;
    color: #64748b;
}

.sidebar .nav-section-label {
    padding: 0.5rem 1rem 0.25rem;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #64748b;
    font-weight: 600;
}
.sidebar .nav-link {
    color: #94a3b8;
    border-radius: 0.375rem;
    margin: 0.1rem 0.5rem;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    transition:
        background 0.15s,
        color 0.15s;
}
.sidebar .nav-link:hover,
.sidebar .nav-link.active {
    background: #334155;
    color: #f1f5f9;
}
.sidebar .nav-link i {
    width: 1.25rem;
    text-align: center;
    margin-right: 0.5rem;
}

.sidebar-footer {
    margin-top: auto;
    padding: 1rem;
    border-top: 1px solid #334155;
}
.sidebar-footer .user-name {
    font-size: 0.8rem;
    color: #f1f5f9;
    font-weight: 600;
}
.sidebar-footer .user-email {
    font-size: 0.7rem;
    color: #64748b;
}

.content-wrapper {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.topbar {
    background: #fff;
    border-bottom: 1px solid #e2e8f0;
    padding: 0.75rem 1.5rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 100;
}
.topbar .page-title {
    font-size: 1.1rem;
    font-weight: 600;
    color: #1e293b;
    margin: 0;
}

main {
    padding: 1.5rem;
    flex: 1;
}

.stat-card {
    border: none;
    border-radius: 0.75rem;
}
.stat-card .stat-icon {
    width: 48px;
    height: 48px;
    border-radius: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
}
.badge-waiting_for_confirmation {
    background-color: #0dcaf0 !important;
}
.badge-pending {
    background-color: #fd7e14 !important;
}
.badge-confirmed {
    background-color: #198754 !important;
}
.badge-cancelled {
    background-color: #6c757d !important;
}
.badge-rejected {
    background-color: #dc3545 !important;
}
.badge-expired {
    background-color: #adb5bd !important;
}

/*
 * Die Layoutauswahl im Displayformular. Die Aufteilung selbst kommt aus dem geteilten Modul
 * oben; hier steht nur die Haut: Format, Farbe, Auswahlzustand.
 */

/*
 * Die Layoutwahl im Editor: eine Reihe Miniaturen, sonst nichts.
 *
 * Eine Aufteilung ist eine **Form**, und die erkennt man schneller, als man „Geteilte Kopfzeile
 * über einer Fläche" liest; acht Kacheln nebeneinander sind außerdem vergleichbar, acht
 * Textblöcke sind eine Wand. Die Namen stehen deshalb im `title` und als `visually-hidden` im
 * Markup — dieselbe Bauart wie bei den Farbtupfern der Flächenwahl darunter.
 */
.layout-choice {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.layout-choice__option {
    position: relative;
    display: block;
    margin: 0;
    cursor: pointer;
}

/* Das Radio bleibt für Tastatur und Screenreader erreichbar und wird nur unsichtbar. Es
   wegzuwerfen (`display: none`) nähme der Auswahl die Bedienbarkeit — die Verwaltungsoberfläche
   einer öffentlichen Stelle muss barrierefrei sein, auch wenn die Anzeige es nicht sein kann. */
.layout-choice__input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

/* Der Rahmen um die Miniatur. Sein Grund ist derselbe wie ihrer — so wirkt die Umrandung wie
   der Rand des Panels und nicht wie ein Kasten darum. */
.layout-choice__body {
    display: block;
    padding: 2px;
    border: 2px solid #cbd5e1;
    border-radius: 0.375rem;
    background: #0f172a;
    transition: border-color 0.15s ease-in-out;
}

.layout-choice__option:hover .layout-choice__body {
    border-color: #94a3b8;
}

.layout-choice__input:checked + .layout-choice__body,
.layout-choice__body--current {
    border-color: var(--bs-primary, #0d6efd);
}

.layout-choice__input:focus-visible + .layout-choice__body,
.layout-choice__option--button:focus-visible .layout-choice__body {
    outline: 2px solid var(--bs-primary, #0d6efd);
    outline-offset: 2px;
}

.layout-thumb {
    display: grid;

    /* Alle Miniaturen tragen die Form des *Panels*, nicht die der Aufteilung: sonst vergleicht
       der Nutzer Formate statt Aufteilungen. */
    aspect-ratio: 9 / 16;

    /* Das Kopfband ist am Gerät ein Anteil der *kurzen Kante* (`vmin`, siehe das Layout-Modul).
       Hier wäre `vmin` das Browserfenster; die Miniatur ist aber immer ein hochkantes 9:16-Panel,
       also ist ihre kurze Kante die Breite — und die beträgt 9/16 der Höhe, auf die sich die
       Prozentangabe der Zeile bezieht. Ohne diese Zeile zeigte die Miniatur ein fast doppelt so
       hohes Band wie der Bildschirm. */
    --display-band-height: calc(var(--display-band-share) * 1% * 9 / 16);
    max-height: 7rem;
    margin: 0 auto;
    border-radius: 0.25rem;
    background: #0f172a;
    overflow: hidden;
}

.layout-thumb__slot {
    background: #cbd5e1;
    box-shadow: inset 0 0 0 1px #0f172a;
}

/* Die Höhe steht **hier** und nicht an `.layout-thumb`: erst mit einer festen Höhe kann das
   Seitenverhältnis 9/16 die Breite ausrechnen. Ohne sie wäre die Miniatur in einer Flex-Reihe
   ohne Maß — `max-height` allein ist keine bestimmte Höhe. */
.layout-choice__body .layout-thumb {
    height: 3.25rem;
    max-height: none;
    margin: 0;
}

/*
 * Die Layoutwahl im Editor ist ein Knopf und kein Radio: sie schaltet über eine Live-Aktion
 * sofort um, es gibt kein Formular zum Absenden. Die Haut ist dieselbe wie bei der
 * Radio-Variante, damit beide Stellen gleich aussehen, falls die Auswahl je wieder in ein
 * Formular wandert.
 */
.layout-choice__option--button {
    padding: 0;
    border: 0;
    background: none;
    text-align: inherit;
    font: inherit;
}

/*
 * Die Bereichseinstellungen im Display-Editor.
 *
 * Zwei Erscheinungsformen, eine Mechanik. Eine **Fläche** zeigt ihre Farbe über `--swatch` aus
 * derselben Custom Property, die am Gerät die Fläche malt (`--surface-*` aus dem geteilten
 * Modul) — eine Vorschau, die ihre eigene Farbe mitbrächte, könnte etwas anderes zeigen als der
 * Bildschirm. Eine **Ausrichtung** hat keine Farbe und zeigt ein Symbol; drei Wörter
 * nebeneinander wären eine Wand aus Text.
 */
.slot-choice {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    padding: 0;
    border: 2px solid var(--bs-border-color);
    background: none;
    cursor: pointer;
}

.slot-choice:hover {
    border-color: var(--bs-secondary);
}

/* Eine Reihe Wahlmöglichkeiten im Dialog „Bereich einstellen". */
.slot-choice-group {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Das Radio bleibt für Tastatur und Vorleseprogramm erreichbar und wird nur unsichtbar. Es
   wegzuwerfen (`display: none`) nähme der Wahl die Bedienbarkeit — die Verwaltungsoberfläche
   einer öffentlichen Stelle muss barrierefrei sein, auch wenn die Anzeige es nicht sein kann. */
.slot-choice__input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.slot-choice:has(.slot-choice__input:checked) {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 3px rgb(var(--bs-primary-rgb) / 25%);
}

.slot-choice--icon:has(.slot-choice__input:checked) {
    color: var(--bs-primary);
}

.slot-choice:has(.slot-choice__input:focus-visible) {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

.slot-choice--surface {
    border-radius: 50%;
    background: var(--swatch);
}

.slot-choice--icon {
    border-radius: 0.35rem;
    color: var(--bs-secondary);
}

/* Der Ring statt einer dickeren Kontur: eine Kontur änderte die Größe des Knopfes, und die Reihe
   spränge beim Wechseln der Wahl. */
.slot-choice--chosen {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 3px rgb(var(--bs-primary-rgb) / 25%);
}

.slot-choice--icon.slot-choice--chosen {
    color: var(--bs-primary);
}

/*
 * Die Inhaltsfläche eines Displays — dieselbe Aufteilung wie am Gerät, mit Inhalt darin.
 *
 * Das Grid kommt aus `modules/_display_layouts.css`, oben importiert. Hier steht nur die Haut:
 * Farben, Abstände, Beschriftungen. Wer eine Aufteilung ergänzt, ergänzt **keine** Zeile in
 * dieser Datei — das ist derselbe Gewinn wie bei den Miniaturen.
 */
.display-canvas {
    display: grid;
    gap: 2px;
    margin: 0 auto;
    padding: 2px;
    border-radius: 0.5rem;

    /* Das Seitenverhältnis kommt als Custom Property von der Komponente (`9 / 16` oder `16 / 9`).
       Die **Breite** gibt den Ausschlag, nicht die Höhe: eine Höhengrenze ließe die Breite
       stehen, und die Fläche wäre dann breiter als hoch, obwohl das Gerät hochkant hängt — das
       Seitenverhältnis ist hier die halbe Auskunft.

       Die halbe Kartenbreite ist gesetzt, weil die Fläche erkennbar sein muss: bei einem
       hochkanten Gerät wird sie damit hoch (Breite × 16/9), und das ist der Preis dafür, dass man
       Bereichsnamen und Inhalte darin lesen kann. */
    aspect-ratio: var(--canvas-ratio);
    width: 50%;

    /* Der dunkle Grund ist der Rahmen des Panels: die Lücken zwischen den Bereichen scheinen
       hindurch, und damit sieht man die Aufteilung auch dort, wo zwei leere Flächen aneinander
       stoßen. */
    background: #0f172a;
}

/* Auf einem schmalen Bildschirm ist die halbe Breite keine Fläche mehr, sondern ein Streifen —
   dort nimmt sie alles, was da ist. */
@media (max-width: 991.98px) {
    .display-canvas {
        width: 100%;
    }
}

.canvas__slot {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
    min-height: 0;
    padding: 0.4rem 0.5rem;
    background: var(--bs-body-bg);

    /* Ein Bereich mit sechs Inhalten passt in einem 15-%-Band nicht. Er scrollt dann, statt die
       Fläche zu sprengen — die Proportionen sind hier die Auskunft, nicht die Vollständigkeit
       auf einen Blick. */
    overflow: auto;
}

.canvas__slot-head {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    font-size: 0.7rem;
    line-height: 1.2;
    color: var(--bs-secondary-color);
}

.canvas__slot-name {
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.canvas__slot-share {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

.canvas__slot-rotates {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    color: var(--bs-info-text-emphasis);
}

.canvas__slot-body {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-height: 0;
}

.canvas__content {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.4rem;
    border: 1px solid var(--bs-border-color);
    border-left: 3px solid var(--bs-primary);
    border-radius: 0.25rem;
    background: var(--bs-tertiary-bg);
    font-size: 0.75rem;
    line-height: 1.2;
}

.canvas__content-icon {
    flex: none;
    color: var(--bs-primary);
}

.canvas__content-label {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: var(--bs-body-color);
    text-decoration: none;
}

.canvas__content-note {
    flex: none;
    margin-left: auto;
    color: var(--bs-secondary-color);
}

/* Pausiert: eingerichtet, aber nicht auf dem Bildschirm. Blass statt versteckt — der
   Unterschied zwischen „eingerichtet" und „wird angezeigt" ist die Auskunft, für die jemand
   diese Seite aufruft. */
.canvas__content--paused {
    border-left-color: var(--bs-secondary);
    opacity: 0.6;
}

.canvas__content--unknown {
    border-left-color: var(--bs-warning);
}

.canvas__empty {
    font-size: 0.7rem;
    color: var(--bs-secondary-color);
    font-style: italic;
}

/* Inhalte ohne Platz in dieser Aufteilung — sie stehen unter der Fläche, weil es in ihr keinen
   Ort für sie gibt. Warngelb, aber kein Alarm: verloren ist nichts, sie sind nur unsichtbar. */
.canvas-orphans {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--bs-border-color);
}

.canvas-orphans__lead {
    margin-bottom: 0.5rem;
    font-size: 0.8125rem;
    color: var(--bs-warning-text-emphasis);
}

.canvas-orphans .table {
    font-size: 0.8125rem;
}

/*
 * Die Bereichskarten des Editors liegen so, wie die Bereiche am Gerät liegen.
 *
 * Dasselbe Raster wie die Bühne (`display__layout--<typ>` mit `display__slot--<schlüssel>` an
 * den Karten, aus `modules/_display_layouts.css`) — eine geteilte Kopfzeile ergibt hier also
 * zwei Karten nebeneinander und die Inhaltsfläche darunter, ohne dass das Template etwas über
 * Aufteilungen wüsste. Kommt ein neuntes Layout dazu, stimmt der Editor von selbst.
 *
 * Geändert wird genau eine Eigenschaft: die **Zeilenhöhe**. Am Gerät teilen sich die Zeilen eine
 * feste Bildschirmfläche (`20 %`, `minmax(0, 1fr)`); hier wäre das falsch — eine Karte mit sechs
 * Inhalten und den Flächenwahlen braucht die Höhe, die sie braucht. Die Aufteilung in Spalten und
 * benannte Flächen bleibt, und genau die ist die Auskunft.
 *
 * Der Attributselektor trifft jede Layoutklasse auf einmal und hat mit (0,2,0) mehr Gewicht als
 * die Regeln des Moduls (0,1,0) — eine Zeile statt einer je Layout, und beim nächsten Layout
 * nichts zu tun.
 */
.slot-grid {
    display: grid;
    gap: 1rem;
    align-items: start;
    margin-bottom: 1rem;
}

.slot-grid[class*="display__layout--"] {
    grid-template-rows: none;
}

/* Unter `lg` ist eine halbe Spalte keine Karte mehr, sondern ein Schacht: die Knopfreihen einer
   Bereichskarte brauchen Breite. Dort liegen die Karten wieder untereinander — und die benannten
   Flächen müssen mit abgeschaltet werden, sonst hielten die Karten an ihrem `grid-area` fest. */
@media (max-width: 991.98px) {
    .slot-grid[class*="display__layout--"] {
        grid-template-columns: none;
        grid-template-areas: none;
    }

    .slot-grid > [class*="display__slot--"] {
        grid-area: auto;
    }
}

/*
 * Eine Inhaltszeile in der Bereichskarte.
 *
 * Sie trug bis zum 09.09.2026 bis zu sieben Knöpfe — Bearbeiten, ein Ziel je freiem Bereich,
 * Pausieren, Entfernen. Bei vier Inhalten waren das über zwanzig, und die Karte war nicht mehr
 * zu lesen. Geblieben sind die Sortierpfeile (ein Klick, ohne Rückfrage, und die Reihenfolge
 * sieht man nur hier) und „Bearbeiten"; alles Übrige steht im Dialog dahinter.
 */
.content-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.content-row__name {
    font-weight: 600;
    min-width: 0;
}

/*
 * Die Typauswahl im Dialog „Inhalt hinzufügen".
 *
 * Jede Wahl ist ein eigenes kleines Formular — der Dialog liegt in einem Turbo-Frame und damit
 * außerhalb der LiveComponent, `live#action` greift dort nicht. Sichtbar ist davon nichts: das
 * Formular hat keine Maße, die Kachel ist der Knopf darin.
 */
.type-choice {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.5rem;
}

.type-choice__option {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    width: 100%;
    height: 100%;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    background: var(--bs-body-bg);
    text-align: left;
    font: inherit;
    cursor: pointer;
    transition:
        border-color 0.15s ease-in-out,
        background 0.15s ease-in-out;
}

.type-choice__option:hover {
    border-color: var(--bs-primary);
    background: var(--bs-tertiary-bg);
}

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

.type-choice__icon {
    flex: none;
    margin-top: 0.15rem;
    color: var(--bs-primary);
}

.type-choice__text {
    display: grid;
    gap: 0.1rem;
    min-width: 0;
}

.type-choice__label {
    font-weight: 600;
    line-height: 1.2;
}

.type-choice__hint {
    font-size: 0.75rem;
    line-height: 1.3;
    color: var(--bs-secondary-color);
}

/*
 * Der Dialog scrollt wieder.
 *
 * Bootstraps Regel für den scrollenden Dialog lautet `.modal-dialog-scrollable .modal-body {
 * overflow-y: auto }` und setzt voraus, dass Kopf, Körper und Fuß **direkte** Flex-Kinder von
 * `.modal-content` sind. Dazwischen liegt hier aber das `<turbo-frame>` — und ein unbekanntes
 * Element ist `display: inline`. Der Körper war damit kein Flex-Element mehr, seine Höhe nicht
 * begrenzt, und ein langes Formular (Uhr, Nachrichten) lief unten aus dem Fenster heraus, ohne
 * dass etwas scrollte.
 *
 * Der Frame reicht die Flex-Spalte deshalb durch. `min-height: 0` ist die Zeile, die man dabei
 * vergisst: ohne sie darf ein Flex-Element nicht unter seine Inhaltshöhe schrumpfen, und der
 * Körper bekäme wieder keine Grenze.
 */
.modal-content > turbo-frame {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

/*
 * Die Vorschau eines Displays: dieselbe Seite wie am Gerät, in einem Iframe.
 *
 * Die Bühne ist der sichtbare Ausschnitt, das Iframe darin trägt die **volle** Bildschirmgröße
 * und wird per `transform: scale()` heruntergerechnet. Höhe und Maßstab setzt
 * `display_preview_controller.js`; hier steht nur, dass verkleinert und nicht abgeschnitten
 * aussieht, was zu groß ist.
 *
 * Der dunkle Grund ist derselbe wie bei den Layout-Miniaturen — der Rahmen des Panels, bevor die
 * Seite darin geladen hat.
 */
.display-preview {
    position: relative;
    min-height: 8rem;
    overflow: hidden;
    border-radius: 0.5rem;
    background: #0f172a;
}

.display-preview__frame {
    position: absolute;
    top: 0;
    left: 0;
    border: 0;
    background: #0f172a;

    /* Ohne diesen Ursprung skalierte das Iframe um seine Mitte und ragte oben aus der Bühne. */
    transform-origin: top left;
}

/*
 * Ein aufklappbarer Abschnitt im Einstellungsdialog (`details_group` am Formularfeld) — etwa der
 * zweite Feed des Nachrichten-Widgets. Ein Rahmen, damit man sieht, welche Felder dazugehören,
 * sobald er offen ist; zugeklappt nur eine Zeile.
 */
.form-details {
    border: var(--bs-border-width) solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    padding: 0.5rem 0.75rem;
}

.form-details__summary {
    cursor: pointer;
}

.form-details[open] > .form-details__summary {
    margin-bottom: 0.75rem;
}

.form-details > .mb-3:last-child {
    margin-bottom: 0.25rem !important;
}
