/*
    Bausteine, die mehr als eine Komponente braucht -- und deshalb nicht scoped sein
    koennen.

    Zwei Gruende, warum es diese Datei gibt:

      1. Scoped CSS kann nicht geteilt werden. Der Anhang-Chip stand deswegen zweimal da,
         in ChatComposer.razor.css und in ChatMessageBubble.razor.css, identisch bis auf
         die Hintergrundfarbe -- ein Unterschied, den niemand entworfen hat.
      2. DevExpress zeichnet sein Markup selbst (DxGrid, DxFormLayout). Die Scope-Kennung
         einer Seite kommt dort nicht an, eine Regel aus einer .razor.css also auch nicht.
*/

/* Ein Anhang-Chip. Steht im Verfasser UND in der Nachrichtenblase. */
.chat-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-1);
    font-size: .8rem;
    padding: .15rem var(--app-space-2);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-pill);
    background: var(--app-surface-2);
}

.chat-chip-size {
    color: var(--app-text-muted);
}

/* Ein Chip, der auf einen Download zeigt, ist ein <a> statt eines <span>. Er soll trotzdem
   wie ein Chip aussehen und nicht wie ein Link im Fliesstext. */
a.chat-chip {
    text-decoration: none;
    color: inherit;
}

a.chat-chip:hover {
    border-color: var(--app-accent);
}

/* Ein Dokument, dessen Text noch gezogen wird. Gedaempft statt bunt: es ist ein
   Zwischenzustand von Sekunden, keine Meldung. */
.chat-chip-busy {
    opacity: .7;
}

/* Gescheitert. Der Grund steht im title-Attribut des Chips. */
.chat-chip-failed {
    border-color: var(--app-danger-border);
    background: var(--app-danger-bg);
    color: var(--app-danger-text);
}

.chat-chip-failed .chat-chip-size {
    color: var(--app-danger-text);
}

/* Das gewaehlte Modell kann die Datei nicht lesen (Modellwechsel nach dem Anhaengen). Eine
   Warnung, kein Fehler: gesendet wird trotzdem, die Datei geht nur mit ihrem Namen mit. */
.chat-chip-unsupported {
    border-color: var(--app-warning-border);
    background: var(--app-warning-bg);
    color: var(--app-warning-text);
}

.chat-chip-unsupported .chat-chip-size {
    color: var(--app-warning-text);
}

/* Der Anhangsmodus je Dokument: ein schlichtes <select> im Chip (wie die Modellauswahl,
   kein DevExpress-Editor -- U3). Randlos, damit der Chip ein Chip bleibt. */
.chat-chip-mode {
    font-size: .75rem;
    border: none;
    border-left: 1px solid var(--app-border);
    background: transparent;
    color: var(--app-text-muted);
    padding: 0 0 0 var(--app-space-1);
    cursor: pointer;
}

.chat-chip-mode:focus-visible {
    outline: 2px solid var(--app-accent);
    outline-offset: 1px;
}

/* Was im Zug mit der Datei passieren wird ("wird durchsucht ..."). Auskunft, gedaempft. */
.chat-chip-hint {
    color: var(--app-text-muted);
    font-style: italic;
}

/* Der Benutzer bekommt etwas anderes, als er gewaehlt hat: als ganz gewuenscht, aber zu
   gross; oder gar nicht durchsuchbar. Dieselbe Farbe wie "nicht unterstuetzt". */
.chat-chip-warn {
    border-color: var(--app-warning-border);
    background: var(--app-warning-bg);
}

.chat-chip-warn .chat-chip-hint {
    color: var(--app-warning-text);
}

/* In der Blase ist der Chip ein Link; das <select> darf nicht hinein (interaktiver Inhalt
   in einem <a>). Beide stehen deshalb in einer gemeinsamen Klammer. */
.chat-chip-group {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-1);
}

/* ---------------------------------------------------------------------------------------
   Der Seitenkopf. Sechs Seiten, ein Rhythmus.

   Die h1 bleibt eine h1: Routes.razor hat <FocusOnNavigate Selector="h1" />, und ohne sie
   landet der Fokus nach einer Navigation nirgends.
   --------------------------------------------------------------------------------------- */
.page-header {
    margin-bottom: var(--app-space-5);
}

.page-header h1 {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: -.01em;
}

.page-lead {
    margin: var(--app-space-2) 0 0;
    max-width: 62ch;
    color: var(--app-text-muted);
}

.page-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--app-space-2);
    margin-top: var(--app-space-4);
}

/* ---------------------------------------------------------------------------------------
   Die Karte. Ein Rand, kein Schatten -- das ist die ganze Abgrenzung.
   --------------------------------------------------------------------------------------- */
.panel {
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius);
    margin-bottom: var(--app-space-4);
    overflow: hidden;
}

.panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-3);
    padding: var(--app-space-3) var(--app-space-4);
    border-bottom: 1px solid var(--app-border);
}

.panel-head h2 {
    margin: 0;
    font-size: .95rem;
    font-weight: 600;
}

.panel-body {
    padding: var(--app-space-4);
}

.panel-body > :last-child {
    margin-bottom: 0;
}

/* Eine Tabelle fuellt die Karte randlos aus, statt in ihr zu schweben. */
.panel > .table {
    margin-bottom: 0;
}

.panel > .table > :not(caption) > * > * {
    padding: var(--app-space-2) var(--app-space-4);
}

.panel > .table th {
    font-weight: 600;
    color: var(--app-text-muted);
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------------------
   Die maschinenlesbaren Bloecke (#status-kv, #config-kv, #admin-kv, #login-kv, #access-kv,
   #circuit-live). Sie sind der Pruefvertrag der Browser-Tests und duerfen weder umbenannt
   werden noch ihren Zeilenaufbau key=value verlieren -- leise werden duerfen sie.

   <details> statt display:none: Playwright liest sie ueber innerText, und das ist
   CSS-abhaengig. In einem zugeklappten <details> faellt innerText auf textContent zurueck
   und behaelt die Zeilenumbrueche; display:none laege einen leeren String zurueck.
   --------------------------------------------------------------------------------------- */
.kv {
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius);
    background: var(--app-surface-2);
    margin-bottom: var(--app-space-4);
}

.kv > summary {
    cursor: pointer;
    padding: var(--app-space-2) var(--app-space-3);
    font-size: .8rem;
    color: var(--app-text-muted);
}

.kv > pre {
    margin: 0;
    padding: 0 var(--app-space-3) var(--app-space-3);
    max-height: 18rem;
    overflow: auto;
    font-family: var(--app-font-mono);
    font-size: .78rem;
    color: var(--app-text-muted);
}

/* ---------------------------------------------------------------------------------------
   Die beiden Haken der Admin-Seiten. Sie standen dort schon als CssClass, ohne dass
   irgendwo eine Regel dazu existierte.

   Sie muessen HIER stehen und nicht in einer .razor.css: DxGrid und DxFormLayout zeichnen
   ihr Markup selbst, die Scope-Kennung der Seite kommt dort nicht an. Gesetzt werden
   DevExpress' eigene Tokens -- die Farben leitet bootstrap-external ohnehin aus --bs-* ab,
   wir korrigieren nur die Form.
   --------------------------------------------------------------------------------------- */
.admin-grid {
    --dxbl-grid-border-width: 0;
    --dxbl-grid-header-bg: var(--app-surface-2);
    --dxbl-grid-hover-bg: var(--app-hover-bg);

    border: 1px solid var(--app-border);
    border-radius: var(--app-radius);
    overflow: hidden;
}

.admin-form {
    padding: var(--app-space-2) 0;

    /* Die Grids stehen auf TextWrapEnabled="false". Das setzt white-space: nowrap auf das
       Wurzelelement des Grids, und white-space vererbt sich -- bis in den Inhalt des
       Bearbeitungsformulars. Zusammen mit dem overflow: hidden oben wurde jeder laengere
       Hinweistext rechts abgeschnitten, statt umzubrechen. */
    white-space: normal;
}

/* Die bekannten Platzhalter unter dem Systemprompt: einzelne Marken, die umbrechen duerfen. */
.chatmodel-vars code {
    margin-right: var(--app-space-1);
    white-space: nowrap;
}

/* Die Vorschau des aufgeloesten Prompts. Sie kann beliebig lang werden und darf weder aus dem
   Formular laufen noch die Seite in die Breite ziehen. */
.chatmodel-preview {
    margin: var(--app-space-2) 0 0;
    padding: var(--app-space-2);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-sm);
    background: var(--app-surface-2);
    white-space: pre-wrap;
    overflow: auto;
    max-height: 20rem;
}

/* Ein schmales Formular (Anmeldung). Ersetzt das inline style="max-width: 24rem". */
.form-narrow {
    max-width: 24rem;
}

/* Ein kleiner maschinenlesbarer Block mitten im Text (z. B. #circuit-live). Gleiche
   Schrift wie .kv, aber ohne Aufklapper -- er ist kurz genug, um stehen zu bleiben. */
.kv-inline {
    margin: 0;
    padding: var(--app-space-2) var(--app-space-3);
    border-radius: var(--app-radius-sm);
    background: var(--app-surface-2);
    font-family: var(--app-font-mono);
    font-size: .78rem;
    color: var(--app-text-muted);
    overflow: auto;
}

/* ---------------------------------------------------------------------------------------
   Bootstraps Schaltflaechen-Varianten.

   Sie sind die EINZIGE Stelle, an der die --bs-*-Bruecke nicht traegt: Bootstrap kompiliert
   .btn-primary und Verwandte mit festen Hex-Werten (--bs-btn-bg: #0d6efd), nicht mit
   var(--bs-primary). Gemessen an bootstrap.min.css. DevExpress dagegen leitet seine
   Knopffarben sehr wohl aus --bs-* ab und braucht hier nichts.

   Ueberschrieben wird nur der Variablensatz, nicht die Regeln -- Groesse, Radius, Fokus und
   Zustaende bleiben Bootstraps.
   --------------------------------------------------------------------------------------- */
.btn-primary {
    --bs-btn-color: var(--app-accent-contrast);
    --bs-btn-bg: var(--app-accent);
    --bs-btn-border-color: var(--app-accent);
    --bs-btn-hover-color: var(--app-accent-contrast);
    --bs-btn-hover-bg: var(--app-accent-hover);
    --bs-btn-hover-border-color: var(--app-accent-hover);
    --bs-btn-active-color: var(--app-accent-contrast);
    --bs-btn-active-bg: var(--app-accent-hover);
    --bs-btn-active-border-color: var(--app-accent-hover);
    --bs-btn-disabled-color: var(--app-accent-contrast);
    --bs-btn-disabled-bg: var(--app-accent);
    --bs-btn-disabled-border-color: var(--app-accent);
    --bs-btn-focus-shadow-rgb: var(--app-accent-rgb);
}

.btn-outline-primary {
    --bs-btn-color: var(--app-accent);
    --bs-btn-border-color: var(--app-accent);
    --bs-btn-hover-color: var(--app-accent-contrast);
    --bs-btn-hover-bg: var(--app-accent);
    --bs-btn-hover-border-color: var(--app-accent);
    --bs-btn-active-color: var(--app-accent-contrast);
    --bs-btn-active-bg: var(--app-accent);
    --bs-btn-active-border-color: var(--app-accent);
    --bs-btn-disabled-color: var(--app-accent);
    --bs-btn-disabled-border-color: var(--app-accent);
    --bs-btn-focus-shadow-rgb: var(--app-accent-rgb);
}

.btn-secondary,
.btn-outline-secondary {
    --bs-btn-color: var(--app-text);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--app-border-strong);
    --bs-btn-hover-color: var(--app-text);
    --bs-btn-hover-bg: var(--app-hover-bg);
    --bs-btn-hover-border-color: var(--app-border-strong);
    --bs-btn-active-color: var(--app-text);
    --bs-btn-active-bg: var(--app-active-bg);
    --bs-btn-active-border-color: var(--app-border-strong);
    --bs-btn-disabled-color: var(--app-text-muted);
    --bs-btn-disabled-border-color: var(--app-border);
}

.btn-danger {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--app-danger);
    --bs-btn-border-color: var(--app-danger);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--app-danger);
    --bs-btn-hover-border-color: var(--app-danger);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--app-danger);
    --bs-btn-active-border-color: var(--app-danger);
    --bs-btn-focus-shadow-rgb: var(--app-danger-rgb);
}

/* ---------------------------------------------------------------------------------------
   Die Inhaltsspalte ist eine Flex-Spalte, damit der Chat genau den Rest der Hoehe fuellen
   und INNEN scrollen kann (siehe MainLayout.razor.css). Das hat eine Nebenwirkung, die
   jede andere Seite trifft: ein Flex-Element hat flex-shrink: 1, wird in einer Spalte also
   auf die Fensterhoehe zusammengedrueckt, sobald der Inhalt laenger ist -- und die Karte
   schnitt die Tabellen dann mitten in der Zeile ab, weil sie fuer ihren Radius
   overflow: hidden traegt.

   Diese Regel steht hier und nicht in MainLayout.razor.css: sie muss den Inhalt von @Body
   treffen, und der traegt die Scope-Kennung des Layouts nicht.

   Nur der Chat will den Rest der Hoehe und holt sich das Schrumpfen ausdruecklich zurueck
   (.chat-page in Chat.razor.css).
   --------------------------------------------------------------------------------------- */
.app-content > * {
    flex-shrink: 0;
}

/* Die Quellen eines Zuges auf der Zeitachse. Eine schlichte Liste: Datei, was mit ihr
   geschah, und der Hinweis darunter, falls einer da ist. */
.chat-source-list {
    list-style: none;
    margin: 0;
    padding: var(--app-space-2) 0 0 0;
}

.chat-source + .chat-source {
    margin-top: var(--app-space-2);
}

.chat-source-detail {
    color: var(--app-text-muted);
    font-size: .85rem;
    margin-left: var(--app-space-2);
}

.chat-source-note {
    color: var(--app-text-muted);
    font-size: .85rem;
}

/* ---------------------------------------------------------------------------------------
   Wissenssammlungen (/admin/knowledge). Der Dokumentteil ist bewusst KEIN DevExpress-Raster,
   deshalb reichen hier gewoehnliche Regeln -- anders als bei .admin-grid gibt es keine
   fremde Scope-Kennung zu umgehen. Sie stehen trotzdem hier und nicht in einer .razor.css,
   damit die Admin-Regeln beieinanderbleiben.
   --------------------------------------------------------------------------------------- */
.knowledge-documents {
    position: relative;
    margin-top: var(--app-space-4);
}

/* Ablageflaeche beim Hineinziehen (filedrop.js setzt data-drop-active). Ein Pseudoelement,
   damit die Ueberlagerung keine Kinder hat, die eigene dragenter/dragleave ausloesen. */
.knowledge-documents[data-drop-active]::after {
    content: "Dateien oder Ordner hier ablegen";
    position: absolute;
    inset: calc(-1 * var(--app-space-2));
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--app-accent);
    border-radius: var(--app-radius-lg);
    /* Fast deckend: durchscheinend kollidierte die Aufschrift mit dem Text darunter. */
    background: color-mix(in srgb, var(--app-surface) 92%, transparent);
    color: var(--app-accent);
    font-size: 1.1rem;
    font-weight: 600;
    pointer-events: none;
}

/* Gesperrt ist das Feld hier nur waehrend eines Hochladens. */
.knowledge-documents[data-drop-active="blocked"]::after,
.knowledge-documents[data-drop-active="busy"]::after {
    content: "Es wird noch hochgeladen …";
}

/* Leer ist die Sammlung selbst die Einladung zum Ablegen. */
.knowledge-empty {
    padding: var(--app-space-5) var(--app-space-3);
    border: 2px dashed var(--app-border-strong);
    border-radius: var(--app-radius-lg);
    text-align: center;
    color: var(--app-text-muted);
}

.knowledge-progress {
    font-variant-numeric: tabular-nums;
    color: var(--app-text-muted);
}

/* Eine Zeile je abgewiesener Datei, hoechstens fuenf (UploadMessages). */
.knowledge-file-error p { margin: 0; }

.knowledge-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--app-space-2);
    align-items: center;
    margin-bottom: var(--app-space-3);
}

.knowledge-table {
    width: 100%;
}

/* Die Fehlermeldung des Extraktors kann eine ganze Stapelspur sein. Sie gehoert an die
   Zeile, darf die Tabelle aber nicht in die Breite ziehen. */
.knowledge-error {
    max-width: 32rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------------------
   Die Rechteverwaltung (PermissionEditor, EffectivePermissionsView, Gruppen-, Benutzer- und
   Systemrechte). Schlichtes HTML statt DevExpress-Editoren (U3) -- die Formen hier.
   --------------------------------------------------------------------------------------- */
.perm-layout {
    display: grid;
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    gap: var(--app-space-4);
    align-items: start;
}

@media (max-width: 1100px) {
    .perm-layout {
        grid-template-columns: minmax(0, 1fr);
    }
}

.perm-section + .perm-section {
    margin-top: var(--app-space-4);
    padding-top: var(--app-space-4);
    border-top: 1px solid var(--app-border);
}

.perm-section h3,
.perm-subtitle {
    margin: 0 0 var(--app-space-2);
    font-size: .9rem;
    font-weight: 600;
}

.perm-group {
    margin-bottom: var(--app-space-3);
}

.perm-group-title {
    font-size: .8rem;
    color: var(--app-text-muted);
    margin-bottom: var(--app-space-1);
}

.perm-check {
    display: flex;
    align-items: baseline;
    gap: var(--app-space-2);
    padding: 2px 0;
}

.perm-check small,
.perm-empty {
    color: var(--app-text-muted);
}

.perm-child {
    padding-left: var(--app-space-4);
}

.perm-parent > span {
    font-weight: 600;
}

.perm-warn {
    color: var(--app-warning-text);
}

.perm-admin {
    padding: var(--app-space-2) var(--app-space-3);
    border-radius: var(--app-radius-sm);
    background: var(--app-success-bg);
    color: var(--app-success-text);
}

.perm-tool-add,
.perm-new-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--app-space-2);
    margin: var(--app-space-2) 0 0 var(--app-space-4);
}

.perm-new-group {
    margin-left: 0;
}

.perm-tool-add input,
.perm-new-group input {
    max-width: 18rem;
}

.perm-level {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-3);
    max-width: 28rem;
    padding: 2px 0;
}

.perm-level select {
    max-width: 9rem;
}

.perm-table .perm-off td {
    color: var(--app-text-muted);
}

.perm-selected td {
    background: var(--app-accent-subtle);
}

.perm-row-actions {
    white-space: nowrap;
    text-align: right;
}

.perm-badge {
    margin-left: var(--app-space-2);
    padding: 0 var(--app-space-2);
    border-radius: var(--app-radius-pill);
    background: var(--app-surface-2);
    color: var(--app-text-muted);
}

.perm-sharing {
    margin-top: var(--app-space-3);
    padding-top: var(--app-space-3);
    border-top: 1px solid var(--app-border);
}

.perm-holders {
    list-style: none;
    margin: 0 0 var(--app-space-2);
    padding: 0;
}

.perm-holders li {
    display: flex;
    align-items: baseline;
    gap: var(--app-space-2);
}

.perm-holders small {
    color: var(--app-text-muted);
}

.perm-new-group select {
    max-width: 18rem;
}

/*
    Das Menue der Modell- und Denkauswahl im Verfasser (DxDropDownButton, DropDownCssClass).
    Es haengt als Portal am <body>, ausserhalb jeder Scope-Kennung -- deshalb hier und nicht
    in Chat.razor.css. Der gewaehlte Eintrag ist fett und traegt einen Haken rechts; ein
    DxDropDownButtonItem kennt keinen Ausgewaehlt-Zustand, die Seite setzt dafuer
    chat-picker-selected als CssClass.
*/
.chat-picker-menu.dxbl-dropdown-dialog {
    min-width: 12rem;
}

/* Jeder Eintrag ueber die volle Breite und linksbuendig -- sonst ist er so breit wie sein
   Text, und der Haken des gewaehlten klebt daran. */
.chat-picker-menu .dxbl-btn-dropdown-item > .dxbl-btn {
    width: 100%;
    justify-content: flex-start;
    font-size: .875rem;
}

.chat-picker-menu .chat-picker-selected {
    font-weight: 600;
}

.chat-picker-menu .chat-picker-selected::after {
    content: "\2713";
    margin-left: auto;
    padding-left: var(--app-space-3);
    color: var(--app-accent);
}

/* Ein gewaehlter Skill (/name) -- im Verfasser UND in der Blase. Akzentgetoent statt grau,
   damit er sich vom Dateianhang unterscheidet: er ist eine Anweisung, keine Datei. */
.chat-chip-skill {
    border-color: var(--app-accent);
    background: var(--app-accent-subtle);
    font-family: var(--app-font-mono);
}

/* ---------------------------------------------------------------------------------------
   Skills: Liste und Editor (SkillLibrary, SkillEditor). Schlichtes HTML (U3).
   --------------------------------------------------------------------------------------- */
.skill-description {
    max-width: 40rem;
}

.skill-actions {
    white-space: nowrap;
    text-align: right;
}

.skill-edit-section {
    margin-top: var(--app-space-4);
    padding-top: var(--app-space-4);
    border-top: 1px solid var(--app-border);
}

.skill-editor {
    display: grid;
    grid-template-columns: minmax(12rem, 1fr) minmax(0, 3fr);
    gap: var(--app-space-4);
    align-items: start;
    margin-top: var(--app-space-3);
}

@media (max-width: 900px) {
    .skill-editor {
        grid-template-columns: minmax(0, 1fr);
    }
}

.skill-editor-files {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-2);
}

.skill-file-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius);
}

.skill-file-list li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--app-space-2);
    padding: 0 var(--app-space-2);
}

.skill-file-list li.active {
    background: var(--app-accent-subtle);
}

.skill-file-list .btn-link {
    font-family: var(--app-font-mono);
    font-size: .85rem;
    text-align: left;
    overflow-wrap: anywhere;
}

.skill-file-add {
    display: flex;
    gap: var(--app-space-1);
}

.skill-file-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-2);
    margin-bottom: var(--app-space-2);
}

.skill-file-head input {
    max-width: 24rem;
    font-family: var(--app-font-mono);
}

.skill-text {
    min-height: 28rem;
    font-family: var(--app-font-mono);
    font-size: .85rem;
    tab-size: 4;
}
