/* Adminoberflaeche. Bewusst eine Datei ohne Build-Schritt. */

:root {
    --bg: #0e1014;
    --panel: #16191f;
    --panel-2: #1d2129;
    --line: #272c36;
    --ink: #e9ecf1;
    --muted: #98a1b0;
    --accent: #9146ff;
    --accent-ink: #ffffff;
    --ok: #3ecf8e;
    --warn: #f5a623;
    --error: #ef4d4d;
    --radius: 12px;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

a { color: inherit; }

/* --- Grundgerüst --------------------------------------------------- */

.shell {
    display: grid;
    grid-template-columns: 248px 1fr;
    min-height: 100vh;
}

/* Genau eine Bildschirmhoehe, nicht mehr und nicht weniger: die Leiste
   bleibt stehen, waehrend der Inhalt scrollt. Wird die Navigation zu
   lang, scrollt sie in sich selbst. */
.sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    min-height: 100vh;
    max-height: 100vh;
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 20px 16px;
    background: var(--panel);
    border-right: 1px solid var(--line);
    overflow: hidden;
}

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
}

.brand strong { display: block; font-size: 1.05rem; }
.brand small { color: var(--muted); font-size: 0.8rem; }

.brand-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 4px rgba(145, 70, 255, 0.18);
}

/* Nimmt den freien Platz und scrollt notfalls selbst, damit der Fuss
   unten kleben bleibt. */
nav {
    flex: 1;
    min-height: 0;
    overflow-y: auto;

    /*
     * Ausdruecklich, nicht nebenbei: ist eine Achse "auto" und die
     * andere "visible", macht der Browser aus "visible" ebenfalls
     * "auto". Sobald die Leiste senkrecht scrollte, nahm ihr Balken
     * Breite weg, die Kinder ragten heraus - und unten erschien ein
     * waagerechter Balken. Waagerecht gibt es hier nichts zu scrollen.
     */
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0 -6px;
    padding: 0 6px;

    /*
     * Der Balken, wenn die Leiste in sich scrollt.
     *
     * Mit zwanzig Plugins passt sie auf 1080 Zeilen nicht mehr, und
     * dann stand der Balken des Betriebssystems da: breit, hell, mit
     * Pfeilen - mitten in einer dunklen Leiste, in der sonst nichts
     * laut ist.
     *
     * Weg kann er nicht: dann waere nicht zu sehen, dass da noch etwas
     * ist. Also schmal und in der Farbe der Trennlinien, und erst beim
     * Zeigen deutlicher. Wer die Maus in der Leiste hat, will
     * scrollen; wer nur hinsieht, soll das Menue sehen.
     */
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
}

/*
 * Dasselbe noch einmal fuer Browser, die nur diesen Weg kennen.
 *
 * Wo BEIDES geht, gewinnt scrollbar-width - die Regeln hier werden
 * dann vollstaendig uebergangen. Das ist kein Versehen und auch kein
 * toter Code: ohne sie bekommt ein aelteres Safari wieder den breiten
 * Balken des Betriebssystems.
 */
nav::-webkit-scrollbar {
    width: 8px;
}

nav::-webkit-scrollbar-track {
    background: transparent;
}

nav::-webkit-scrollbar-thumb {
    background: var(--line);
    border-radius: 999px;

    /* Der Rand ist durchsichtig und gehoert zum Griff: so sieht er
       schmaler aus, als die Flaeche ist, die man treffen muss. */
    border: 2px solid transparent;
    background-clip: content-box;
}

nav:hover {
    scrollbar-color: var(--muted) transparent;
}

nav:hover::-webkit-scrollbar-thumb {
    background: var(--muted);
    background-clip: content-box;
}

/* --- Einklappbare Gruppen -------------------------------------------- */

.nav-group { display: block; }

summary.nav-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.7rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--muted);
    padding: 7px 10px 6px;
    cursor: pointer;
    border-radius: 8px;
    list-style: none;
    user-select: none;
}

summary.nav-label::-webkit-details-marker { display: none; }
summary.nav-label:hover { color: var(--ink); background: var(--panel-2); }

/* Pfeil davor, dreht sich beim Aufklappen. */
summary.nav-label::before {
    content: "";
    width: 0;
    height: 0;
    border-left: 4px solid currentColor;
    border-top: 3.5px solid transparent;
    border-bottom: 3.5px solid transparent;
    transition: transform 0.15s ease;
    flex: none;
}

.nav-group[open] > summary.nav-label::before { transform: rotate(90deg); }

.nav-links {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: 6px;
}

.nav-item {
    padding: 8px 10px;
    border-radius: 9px;
    text-decoration: none;
    color: var(--ink);
    font-size: 0.93rem;
}

.nav-item:hover { background: var(--panel-2); }

.nav-item.is-active {
    background: rgba(145, 70, 255, 0.16);
    color: #d9c6ff;
    font-weight: 600;
}

.sidebar-foot {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 16px;
    border-top: 1px solid var(--line);
}

.who strong { display: block; font-size: 0.9rem; }
.who small { color: var(--muted); font-size: 0.78rem; }

/*
 * Keine Breitenbegrenzung: Rechteraster, Tabellen und die
 * mehrspaltigen Formulare brauchen den Platz. Eine Grenze hier hiess
 * links quetschen und rechts leer lassen.
 *
 * Begrenzt wird stattdessen der Fliesstext - siehe .lead und .prose.
 * Dort zaehlt Lesbarkeit, bei einem Raster nicht.
 */
.content { padding: 32px 36px 64px; }

/* --- Textbausteine ------------------------------------------------- */

h1 { font-size: 1.5rem; margin: 0 0 6px; }
h2 { font-size: 1.1rem; margin: 28px 0 12px; }
.lead { color: var(--muted); margin: 0 0 26px; max-width: 78ch; }

.card {
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 20px;
    margin-bottom: 16px;
}

.card > h2:first-child { margin-top: 0; }

.card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    margin-bottom: 14px;
}

.card-head h2 { margin: 0; }

.hint { color: var(--muted); font-size: 0.86rem; }
.stack { display: flex; flex-direction: column; gap: 14px; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/*
 * hidden soll verbergen. Ueberall.
 *
 * [hidden] { display: none } ist nur eine Vorgabe des Browsers, und
 * JEDE Autoren-Regel schlaegt sie - "display: flex" auf .row zum
 * Beispiel. Ein el.hidden = true tat dort also nichts, und man sucht
 * den Fehler im JavaScript, wo keiner ist.
 *
 * Dieselbe Falle hatte das Overlay schon einmal; dort steht die
 * Berichtigung oertlich in goals.css. Hier gilt sie fuer die ganze
 * Oberflaeche - eine Ausnahme davon waere ein Element, das verborgen
 * sein soll und trotzdem Platz nimmt, und das gibt es nicht.
 */
[hidden] { display: none !important; }

/*
 * Steht eine Zeile direkt vor einer Karte - etwa ein
 * "Zurueck"-Knopf - klebte die Karte bisher daran. .card hat nur
 * Abstand nach unten; das hier ergaenzt ihn nach oben, aber nur dort,
 * wo er fehlt.
 */
.row + .card { margin-top: 16px; }
.grow { flex: 1; }
.right { margin-left: auto; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.86rem; }

/* --- Formulare ----------------------------------------------------- */

label { display: block; font-size: 0.86rem; color: var(--muted); margin-bottom: 5px; }

.input, select, textarea {
    width: 100%;
    padding: 10px 12px;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 9px;
    color: var(--ink);
    font: inherit;
}

.input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--accent);
}

.field { margin-bottom: 14px; }

/*
 * Alle Knöpfe haben EINE Höhe.
 *
 * Vorher gab es zwei: .btn mit 10px Polsterung und Fließtextgröße war
 * so hoch wie ein .input (rund 45px), .btn-small mit 6px und 0.85rem
 * rund 34px. Welche ein Knopf bekam, hing davon ab, welche Klasse eine
 * Ansicht zufällig benutzte — auf einer Seite standen dadurch zwei
 * verschieden hohe Knöpfe nebeneinander.
 *
 * Maßgeblich ist jetzt die kompakte Form. Ein Knopf ist damit niedriger
 * als das Eingabefeld daneben, und das ist Absicht: er soll nicht so
 * schwer wirken wie das Feld, in das man schreibt.
 *
 * line-height steht ausdrücklich hier. Mit dem geerbten 1.55 des
 * Fließtextes wäre die Zeilenbox höher als der Text braucht, und die
 * Höhe hinge an einer Einstellung, die für Absätze gedacht ist.
 */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    border: 1px solid transparent;
    border-radius: 9px;
    background: var(--accent);
    color: var(--accent-ink);
    font: inherit;
    font-size: 0.88rem;
    line-height: 1.45;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;

    /*
     * Die Beschriftung bleibt in einer Zeile.
     *
     * Ohne das wird ein Knopf im schmalen Fenster doppelt oder dreifach
     * hoch: "Muster hinzufügen" bricht um, und aus 36px werden 57 oder
     * 77. Gemessen im Browser, nicht geschätzt - auf dem Handy war
     * genau das der Grund, warum die Knöpfe zu hoch aussahen.
     *
     * Passt er nicht mehr in die Zeile, schiebt ihn .row in die
     * nächste - das ist richtig, denn ein Knopf ist so breit wie sein
     * Text.
     */
    white-space: nowrap;
}

.btn:hover { filter: brightness(1.1); }

.btn-ghost {
    background: transparent;
    border-color: var(--line);
    color: var(--ink);
    font-weight: 500;
}

.btn-danger { background: transparent; border-color: rgba(239, 77, 77, 0.5); color: #ff9a9a; }
/*
 * .btn-small ist keine eigene Größe mehr.
 *
 * Die Klasse bleibt, weil sie in Markup steht, das schon ausgeliefert
 * ist: ein installiertes Plugin bringt seine Vorlagen selbst mit und
 * lässt sich nicht im Gleichschritt mit dem Kern ändern. Würde sie
 * hier verschwinden, sähen deren Knöpfe plötzlich anders aus als die
 * daneben — genau der Zustand, den diese Änderung beseitigt.
 *
 * Für neues Markup ist sie überflüssig.
 */
.btn-small { /* absichtlich leer - siehe oben */ }

/* --- Meldungen ----------------------------------------------------- */

.note {
    padding: 12px 14px;
    border-radius: 10px;
    margin-bottom: 16px;
    border: 1px solid var(--line);
    background: var(--panel-2);
}

/*
 * Steht eine Meldung nicht am Anfang, braucht sie Abstand nach oben.
 *
 * .note hatte nur margin-bottom - richtig für die Meldungen, die oben
 * auf einer Seite stehen. Erscheint sie aber als Antwort UNTER etwas,
 * etwa das Ergebnis des Testfelds im Löschbot unter dem Knopf
 * "Prüfen", klebte sie daran.
 *
 * Zwei Meldungen untereinander rücken dadurch nicht auseinander: in
 * einem normalen Block fallen benachbarte Ränder zusammen, aus 16
 * unten und 16 oben werden 16 - nicht 32.
 */
* + .note { margin-top: 16px; }

.note-ok    { border-color: rgba(62, 207, 142, 0.4); background: rgba(62, 207, 142, 0.1); }
.note-warn  { border-color: rgba(245, 166, 35, 0.4); background: rgba(245, 166, 35, 0.1); }
.note-error { border-color: rgba(239, 77, 77, 0.45); background: rgba(239, 77, 77, 0.1); }

.badge {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 0.76rem;
    font-weight: 600;
    background: var(--panel-2);
    color: var(--muted);
}

.badge-ok    { background: rgba(62, 207, 142, 0.16); color: var(--ok); }
.badge-warn  { background: rgba(245, 166, 35, 0.16); color: var(--warn); }
.badge-error { background: rgba(239, 77, 77, 0.16); color: #ff9a9a; }
.badge-off   { background: var(--panel-2); color: var(--muted); }

/* --- Tabellen ------------------------------------------------------ */

table { width: 100%; border-collapse: collapse; }

th, td {
    text-align: left;
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
    vertical-align: middle;
}

th { font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
tbody tr:last-child td { border-bottom: none; }
td.actions { text-align: right; white-space: nowrap; }

.empty { padding: 28px; text-align: center; color: var(--muted); }

/* --- Rechte-Auswahl ------------------------------------------------ */

.perm-group { border: 1px solid var(--line); border-radius: 10px; padding: 14px; margin-bottom: 12px; }
.perm-group h3 { margin: 0 0 10px; font-size: 0.95rem; }
.perm { display: flex; gap: 9px; align-items: flex-start; padding: 5px 0; }
.perm input { margin-top: 3px; }
.perm span { font-size: 0.88rem; }
.perm code { color: var(--muted); font-size: 0.8rem; }

/*
 * Rechteseite: ein Kasten je Bereich, darin die Funktionen als
 * Zwischentitel und deren Rechte nebeneinander. Bei knapp hundert
 * Kaestchen ist diese Gliederung der Unterschied zwischen benutzbar
 * und unbenutzbar - untereinander waere das eine Bildschirmlaenge
 * ohne Halt.
 */
.perm-feature { margin: 0 0 18px; }
.perm-feature:last-child { margin-bottom: 0; }
.perm-feature h3 {
    margin: 0 0 8px;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--ink);
}

.perm-grid {
    display: grid;
    /* auto-fill statt fester Spalten: auf einem schmalen Fenster
       werden es von allein weniger. */
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 4px 18px;
}

.perm-grid .perm {
    padding: 6px 8px;
    border-radius: 7px;
    cursor: pointer;
}
.perm-grid .perm:hover { background: var(--panel-2); }

/* Klarname fett, Erklaerung darunter klein - so ist die Zeile auf
   einen Blick zu erfassen und die Erklaerung trotzdem da. */
.perm-grid .perm span { display: flex; flex-direction: column; gap: 1px; }
.perm-grid .perm strong { font-weight: 500; font-size: 0.88rem; }
.perm-grid .perm .hint { font-size: 0.78rem; line-height: 1.35; }

/* --- Login und Einrichtung ----------------------------------------- */

.centered {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 32px 20px;
}

.panel {
    width: min(560px, 100%);
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 16px;
    padding: 30px;
}

.steps { display: flex; gap: 8px; margin-bottom: 24px; }

.step {
    flex: 1;
    height: 4px;
    border-radius: 999px;
    background: var(--line);
}

.step.is-done { background: var(--ok); }
.step.is-current { background: var(--accent); }

@media (max-width: 820px) {
    .shell { grid-template-columns: 1fr; }

    /* Auf schmalen Geraeten liegt die Leiste oben - dort waere eine
       feste Bildschirmhoehe die ganze Seite. */
    .sidebar {
        position: static;
        height: auto;
        min-height: 0;
        max-height: none;
        overflow: visible;
        border-right: none;
        border-bottom: 1px solid var(--line);
    }

    nav { overflow: visible; }
    .sidebar-foot { margin-top: 16px; }
    .content { padding: 22px 18px 48px; }
}

/* Menuepunkt mit Schnellschalter daneben. */
.nav-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.nav-row .nav-item {
    flex: 1;
    min-width: 0;
}

/*
 * Zweite Bauform: ein Schalter, der zu einem Formular gehoert und erst
 * beim Speichern wirkt. Innen eine gewoehnliche Checkbox - sie schickt
 * ihren Wert mit, ist mit der Tastatur bedienbar und braucht kein
 * JavaScript. Sichtbar ist nur die Pille davor.
 *
 * Die erste Bauform (.switch als Absende-Knopf) wirkt sofort. Beide
 * sehen gleich aus, damit "an/aus" ueberall dasselbe Bild hat.
 */
.switch-field {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    cursor: pointer;
}

.switch-field input {
    /* Nicht display:none - dann waere sie nicht mehr fokussierbar. */
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    margin: 0;
}

.switch-field .switch-track {
    flex: 0 0 auto;
    margin-top: 2px;
}

.switch-field input:checked + .switch-track {
    background: var(--accent);
}

.switch-field input:checked + .switch-track .switch-knob {
    transform: translateX(24px);
}

.switch-field input:focus-visible + .switch-track {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

.switch-field input:disabled + .switch-track {
    opacity: 0.5;
    cursor: default;
}

/* --- Kopfzeile mit Bedienelement ----------------------------------- */

/*
 * Titel links, ein Schalter oder Knopf rechts. Steht im Kern und nicht
 * im Plugin: es ist eine Anordnung, kein Alert-Detail - und ein
 * Plugin-Stylesheet kann fehlen.
 */
.head-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin: 0 0 6px;
}

.head-row > h1,
.head-row > h2,
.head-row > h3 {
    margin: 0;
}

/* --- Feld mit Dateiauswahl ----------------------------------------- */

/*
 * Adresse eintippen oder eine Datei wählen - beides an derselben
 * Stelle. Der Knopf sitzt rechts am Feld und löst die verborgene
 * Dateiauswahl aus; das Original von <input type="file"> ist
 * ausgeblendet, weil "Choose File / No file chosen" nichts erklärt und
 * sich nicht gestalten lässt.
 */
.file-field {
    display: flex;
    align-items: stretch;

    /* Ein Feld, nicht zwei Elemente: der Rahmen umschliesst beides. */
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--bg);
    overflow: hidden;
}

.file-field:focus-within {
    border-color: var(--accent);
}

/* Das Textfeld gibt seinen eigenen Rahmen ab - den hat jetzt die
   Umhuellung. */
.file-field .input {
    flex: 1;
    min-width: 0;
    border: 0;
    border-radius: 0;
    background: none;
}

.file-field .input:focus {
    outline: none;
}

.file-field-button {
    flex: 0 0 auto;
    width: 40px;
    border: 0;
    border-left: 1px solid var(--line);
    background: var(--panel-2);
    color: var(--muted);
    cursor: pointer;
    font: inherit;
    font-size: 1.05rem;
    line-height: 1;
}

.file-field-button:hover {
    background: var(--accent);
    color: var(--accent-ink);
}

.file-field-button:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* Der Browserknopf selbst bleibt unsichtbar - er wird über den
   eigenen ausgelöst. */
.file-field-native {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/*
 * Was beim Hochladen zu sagen ist: "wird hochgeladen", oder warum es
 * nicht ging. Die Zeile baut das Skript im Rahmen und steht unter dem
 * Feld - so muss keine der Plugin-Vorlagen dafuer angefasst werden.
 *
 * Ohne Meldung ist sie hidden und nimmt keinen Platz weg: eine leere
 * Zeile unter jedem Dateifeld waere ein Abstand ohne Grund.
 */
.file-field-note {
    margin: 6px 0 0;
}

.file-field-error {
    color: var(--error);
}

/* --- Aufklappbarer Fall -------------------------------------------- */

/*
 * Ein Alert hat mehrere Fälle - erster Sub, Resub, Resub mit Streak -
 * und jeder davon Text, Video, Ton und Dauer. Untereinander aufgeklappt
 * wären das mehrere Bildschirmlängen.
 */
.case {
    border: 1px solid var(--line);
    border-radius: 10px;
    margin-bottom: 10px;
    background: var(--panel-2);
}

.case > summary {
    padding: 11px 14px;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.92rem;
    list-style: none;
}

.case > summary::-webkit-details-marker,
.case > summary::marker {
    display: none;
    content: "";
}

.case > summary::before {
    content: "▸";
    display: inline-block;
    width: 1em;
    color: var(--muted);
}

.case[open] > summary::before {
    content: "▾";
}

.case-body {
    padding: 4px 14px 14px;
    border-top: 1px solid var(--line);
}

/* Platzhalter-Zeile über den Fällen. */
.placeholders code {
    margin-right: 6px;
}

/* --- Kippschalter -------------------------------------------------- */

/*
 * Ein An/Aus-Schalter. Gehört in den Kern und nicht in ein Plugin:
 * es ist ein allgemeines Bedienelement, jedes Plugin soll denselben
 * bekommen - und ein Plugin-Stylesheet kann fehlen. Dann sah der
 * Schalter aus wie ein nackter Knopf mit "An" darin.
 *
 * Gebaut als Formular-Knopf, nicht als Checkbox: so wird ohne
 * JavaScript geschaltet, und mit der Tastatur ist er erreichbar.
 * Beschriftung steckt im title/aria-label, weil der Schalter selbst
 * schon zeigt, in welchem Zustand er ist.
 */
.switch {
    display: inline-flex;
    align-items: center;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    line-height: 0;
}

.switch-track {
    position: relative;
    display: block;
    width: 52px;
    height: 28px;
    border-radius: 999px;
    background: var(--line);
    transition: background 160ms ease-out;

    /*
     * Sicherheitsnetz: eine falsch berechnete Verschiebung des Knopfes
     * bleibt damit ein Schoenheitsfehler und wird nicht zum
     * Layoutfehler. Eine Verschiebung erzeugt Ueberlauf, und der
     * schlug bis in die Seitenleiste durch - als waagerechter
     * Scrollbalken.
     */
    overflow: hidden;
}

.switch-knob {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    transition: transform 160ms ease-out;
}

.switch.is-on .switch-track {
    background: var(--accent);
}

.switch.is-on .switch-knob {
    transform: translateX(24px);
}

/*
 * Kleine Ausfuehrung fuer die Seitenleiste - der grosse Schalter
 * wuerde dort den Platz sprengen.
 *
 * Muss NACH den Grundregeln stehen: ".switch-small.is-on .switch-knob"
 * und ".switch.is-on .switch-knob" haben dieselbe Spezifitaet, also
 * gewinnt die spaetere. Stand sie davor, bekam der kleine Knopf die
 * Verschiebung des grossen - 24px auf einer 34px-Schiene. Er ragte
 * heraus, und weil eine Verschiebung Ueberlauf erzeugt, bekam die
 * Seitenleiste davon einen waagerechten Scrollbalken.
 */
.switch-small .switch-track { width: 34px; height: 19px; }
.switch-small .switch-knob { width: 15px; height: 15px; top: 2px; left: 2px; }
.switch-small.is-on .switch-knob { transform: translateX(15px); }

.switch:hover .switch-track {
    /* Nur ein Hauch - der Schalter soll nicht blinken, wenn die Maus
       zufaellig darueber wandert. */
    filter: brightness(1.15);
}

.switch:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: 999px;
}

@media (prefers-reduced-motion: reduce) {
    .switch-track,
    .switch-knob {
        transition: none;
    }
}

/* --- Rückfrage ----------------------------------------------------- */

/*
 * Ein Kasten, der unter dem Knopf aufklappt - statt confirm(). Der
 * Browserdialog ist nicht gestaltbar und schreibt den Domainnamen
 * darüber; das sieht nach Fehlermeldung aus, nicht nach Rückfrage.
 *
 * Gebaut auf <details>: klappt ohne JavaScript auf und zu.
 */
.confirm {
    position: relative;
    display: inline-block;
}

/* Das <summary> IST der Knopf. Der Marker muss weg. */
.confirm > summary {
    list-style: none;
    cursor: pointer;
}

.confirm > summary::-webkit-details-marker,
.confirm > summary::marker {
    display: none;
    content: "";
}

.confirm-panel {
    position: absolute;
    z-index: 40;
    top: calc(100% + 6px);
    left: 0;
    width: max(280px, 100%);
    max-width: min(420px, 90vw);
    padding: 14px;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);

    /* Der Schatten trennt den Kasten von der Karte darunter - ohne ihn
       sieht er wie ein weiterer Abschnitt aus. */
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}

/* Nach links öffnen, wenn der Knopf am rechten Rand sitzt.
   confirm-right setzt die Vorlage, confirm-flip das Skript, wenn es
   beim Öffnen merkt, dass der Kasten sonst aus dem Fenster ragt. */
.confirm.confirm-right .confirm-panel,
.confirm.confirm-flip .confirm-panel {
    left: auto;
    right: 0;
}

.confirm-question {
    margin: 0 0 10px;
    font-size: 0.9rem;
    line-height: 1.45;

    /* Die Fragen enthalten Zeilenumbrüche - die sollen wirken. */
    white-space: pre-line;
}

/* --- Reiter -------------------------------------------------------- */

/*
 * Reiter als Schalterleiste in einem eigenen Kasten.
 *
 * Vorher waren es Ordner-Reiter: oben abgerundet, ohne Unterkante, um
 * einen Pixel nach unten geschoben - gedacht, um auf der Linie zu
 * sitzen und in den Inhalt darunter uebergehen. Darunter standen aber
 * 22px Abstand, und damit hing die offene Unterkante in der Luft.
 *
 * Ein eigener Kasten braucht diesen Trick nicht: er darf Abstand nach
 * unten haben, ohne dass etwas unfertig aussieht.
 */
.tabs {
    display: inline-flex;
    gap: 3px;
    margin: 0 0 20px;
    padding: 4px;
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 999px;

    /* Bei vielen Reitern - die Alert-Seite hat sechs - umbrechen statt
       ueber den Rand hinauslaufen. */
    flex-wrap: wrap;
}

.tab {
    padding: 7px 15px;
    border-radius: 999px;
    text-decoration: none;
    color: var(--muted);
    font-size: 0.9rem;
    white-space: nowrap;
}

.tab:hover { color: var(--ink); }

.tab.is-active {
    color: var(--ink);
    font-weight: 600;
    background: var(--panel);

    /* Ein Hauch Tiefe, damit der aktive Reiter aus der Leiste
       heraussteht und nicht nur heller ist. */
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

/* --- Beschreibungstexte aus dem Katalog ---------------------------- */

/* Fliesstext begrenzen, nicht die Seite - eine Zeile ueber die ganze
   Breite eines grossen Bildschirms liest niemand gern. */
.prose { max-width: 82ch; }
.prose p { margin: 0 0 12px; }
.prose p:last-child { margin-bottom: 0; }
.prose ul { margin: 0 0 12px; padding-left: 22px; }
.prose li { margin: 3px 0; }
.prose code {
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 5px;
    padding: 1px 5px;
    font-size: 0.88em;
}

/* --- Bilder auf der Detailseite ------------------------------------ */

.shots {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 6px;
}

.shots img {
    height: 180px;
    width: auto;
    border-radius: 10px;
    border: 1px solid var(--line);
    display: block;
}

/* -------------------------------------------------------------------
 *  Knappe Plugin-Liste
 *
 *  Eine Zeile je Plugin: Name, Zustand, Knoepfe. Wer zehn Plugins hat,
 *  scrollt sonst an Beschreibungen und Abhaengigkeiten vorbei, um an
 *  den Schalter zu kommen - und genau dafuer kommt man auf die Seite.
 *
 *  Kein eigener Kasten je Zeile, sondern ein durchgehender Block mit
 *  Trennlinien: zehn Kaesten mit Abstand dazwischen sind wieder eine
 *  lange Seite, nur mit weniger Inhalt.
 * ------------------------------------------------------------------- */
.plugin-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;

    background: var(--panel);
    border: 1px solid var(--line);
    border-bottom: 0;
    padding: 7px 14px;
}

/* Die letzte Zeile schliesst den Block ab. */
.plugin-row:last-of-type { border-bottom: 1px solid var(--line); }

/* Ecken nur aussen - innen stossen die Zeilen aneinander. */
.plugin-row:first-of-type { border-radius: var(--radius) var(--radius) 0 0; }
.plugin-row:last-of-type { border-radius: 0 0 var(--radius) var(--radius); }

/* Steht eine Warnung dazwischen, endet der Block davor und beginnt
   danach neu - sonst haengt die Warnung ohne Rand in der Reihe. */
.plugin-row + .note { margin: 0 0 10px; border-radius: 0 0 var(--radius) var(--radius); }
.plugin-row-note + .plugin-row { border-radius: var(--radius) var(--radius) 0 0; }

.plugin-row-name {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

/* Der Name darf kuerzen, die Knoepfe nicht - sie sind der Grund, warum
   man hier ist. */
.plugin-row-name strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.plugin-row .row { flex: 0 0 auto; }

/* Der Umschalter sitzt rechts ueber der Liste. */
.view-switch {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 10px;
}

/*
 * Der Streifen, der sagt: es passiert gerade etwas.
 *
 * Seit Formulare ohne Seitenwechsel abgeschickt werden, fehlt die
 * Rueckmeldung, die der Browser frueher von selbst gab - beim Laden
 * drehte sich sein Rad. "Alle aktualisieren" holt Dateien von einem
 * anderen Server und dauert; ohne ein Zeichen sieht das aus, als waere
 * der Klick ins Leere gegangen, und man klickt noch einmal.
 *
 * Oben quer statt als Rad in der Mitte: es verdeckt nichts und haelt
 * niemanden auf. Wer weiterlesen will, kann das.
 */
#ov-busy {
    position: fixed;
    left: 0;
    top: 0;
    height: 2px;
    width: 100%;
    z-index: 9999;

    /* Unsichtbar, solange nichts laeuft - aber im Dokument: ein
       Element, das erst entsteht, kann nicht ueberblenden. */
    opacity: 0;
    transition: opacity 0.15s ease;
    pointer-events: none;
    background: linear-gradient(90deg,
        transparent 0%, var(--accent) 40%, var(--accent) 60%, transparent 100%);
    background-size: 40% 100%;
    background-repeat: no-repeat;
}

html[data-busy="1"] #ov-busy {
    opacity: 1;
    animation: ov-busy-lauf 1.1s ease-in-out infinite;
}

@keyframes ov-busy-lauf {
    from { background-position: -40% 0; }
    to   { background-position: 140% 0; }
}

/* Wer Bewegung abgestellt hat, bekommt den Streifen ruhig - aber er
   ist da, und das ist die Auskunft, um die es geht. */
@media (prefers-reduced-motion: reduce) {
    html[data-busy="1"] #ov-busy {
        animation: none;
        background-size: 100% 100%;
    }
}
