/*
 * Grundlagen: Design-Variablen, Reset, Typografie, Formulare.
 *
 * Board- und Kartenstile liegen bewusst in eigenen Dateien und werden als
 * eigene <link>-Tags eingebunden. AssetMapper schreibt Pfade in @import nicht
 * zuverlaessig um, deshalb wird auf @import verzichtet.
 *
 * Aufbau der Farbwerte: Es gibt drei Flaechenebenen — die Arbeitsflaeche
 * (--c-bg), das Blatt darauf (--c-surface) und die gedaempfte Ebene fuer
 * Leisten, Tabellenkoepfe und Spalten (--c-surface-alt). Rahmen kommen in zwei
 * Staerken: --c-border traegt gewoehnliche Trennungen, --c-border-strong
 * markiert Bedienelemente, die anfassbar sein sollen. Ohne diese Trennung
 * wirken Eingabefelder entweder zu blass oder alle Kanten zu laut.
 */

:root {
    color-scheme: light dark;

    --c-bg:           #f1f3f6;
    --c-surface:      #ffffff;
    --c-surface-alt:  #f5f6f9;
    --c-surface-sunk: #eceef3;
    --c-border:       #e3e6ec;
    --c-border-strong:#c9cfda;
    --c-text:         #171a1f;
    --c-text-muted:   #5b6472;

    --c-accent:        #2f6fed;
    --c-accent-strong: #2159cf;
    --c-accent-text:   #ffffff;
    --c-accent-soft:   #e8effd;
    --c-ring:          rgb(47 111 237 / .3);

    --c-danger:       #c0392e;
    --c-danger-soft:  #fceceb;
    --c-success:      #16704a;
    --c-success-soft: #e2f3ea;
    --c-warning:      #a35a09;
    --c-warning-soft: #fdf1dc;

    --radius-sm: 5px;
    --radius:    8px;
    --radius-lg: 12px;
    --radius-pill: 999px;
    --gap:       1rem;

    /* Gemeinsame Hoehe fuer Eingabefelder und Schaltflaechen. Nur dadurch
       stehen sie in einer Zeile wirklich auf einer Linie. */
    --control-h: 2.25rem;
    --header-h:  3.25rem;

    /* Schatten mit Versatz und weichem Verlauf. Ein Schein ohne Versatz sieht
       nach Leuchten aus, nicht nach Hoehe. */
    --shadow-1: 0 1px 2px rgb(16 24 40 / .06), 0 1px 1px rgb(16 24 40 / .04);
    --shadow-2: 0 4px 12px -2px rgb(16 24 40 / .10), 0 2px 4px -2px rgb(16 24 40 / .05);
    --shadow-3: 0 18px 36px -12px rgb(16 24 40 / .22), 0 4px 10px -4px rgb(16 24 40 / .08);

    --t: 140ms cubic-bezier(.2, .8, .3, 1);

    --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace;
}

@media (prefers-color-scheme: dark) {

:root:not([data-theme="light"]) {
        --c-bg:           #101317;
        --c-surface:      #1a1e24;
        --c-surface-alt:  #21262e;
        --c-surface-sunk: #14181d;
        --c-border:       #2c323b;
        --c-border-strong:#414956;
        --c-text:         #e9ecf1;
        --c-text-muted:   #98a2b3;

        --c-accent:        #5b93ff;
        --c-accent-strong: #7aa8ff;
        --c-accent-text:   #0b1220;
        --c-accent-soft:   #1b2740;
        --c-ring:          rgb(91 147 255 / .35);

        --c-danger:       #f08279;
        --c-danger-soft:  #35201e;
        --c-success:      #5ec895;
        --c-success-soft: #142c22;
        --c-warning:      #e3a55c;
        --c-warning-soft: #31260f;

        --shadow-1: 0 1px 2px rgb(0 0 0 / .5);
        --shadow-2: 0 4px 12px -2px rgb(0 0 0 / .55), 0 2px 4px -2px rgb(0 0 0 / .4);
        --shadow-3: 0 18px 36px -12px rgb(0 0 0 / .7), 0 4px 10px -4px rgb(0 0 0 / .5);
    }
}

/* Dieselben Werte fuer die ausdrueckliche Wahl „dunkel". Eine
   Medienabfrage laesst sich nicht mit einem Attributselektor verunden,
   deshalb steht der Block zweimal da; erzeugt aus dem Block darueber. */

:root[data-theme="dark"] {
        --c-bg:           #101317;
        --c-surface:      #1a1e24;
        --c-surface-alt:  #21262e;
        --c-surface-sunk: #14181d;
        --c-border:       #2c323b;
        --c-border-strong:#414956;
        --c-text:         #e9ecf1;
        --c-text-muted:   #98a2b3;

        --c-accent:        #5b93ff;
        --c-accent-strong: #7aa8ff;
        --c-accent-text:   #0b1220;
        --c-accent-soft:   #1b2740;
        --c-ring:          rgb(91 147 255 / .35);

        --c-danger:       #f08279;
        --c-danger-soft:  #35201e;
        --c-success:      #5ec895;
        --c-success-soft: #142c22;
        --c-warning:      #e3a55c;
        --c-warning-soft: #31260f;

        --shadow-1: 0 1px 2px rgb(0 0 0 / .5);
        --shadow-2: 0 4px 12px -2px rgb(0 0 0 / .55), 0 2px 4px -2px rgb(0 0 0 / .4);
        --shadow-3: 0 18px 36px -12px rgb(0 0 0 / .7), 0 4px 10px -4px rgb(0 0 0 / .5);
    }



*, *::before, *::after { box-sizing: border-box; }

/*
 * Die Seite ist eine senkrechte Spalte über die volle Fensterhöhe: Kopfzeile
 * oben in ihrer natürlichen Höhe, Inhalt darunter mit dem Rest.
 *
 * Das Board braucht diesen Rest als *gemessene* Höhe, damit die Spaltenköpfe
 * stehen bleiben, während man in einer langen Spalte blättert. Vorher stand
 * dort `calc(100vh - 49px)` mit der Kopfhöhe als fester Zahl — die stimmte,
 * bis die Kopfzeile auf einem schmalen Bildschirm zweizeilig umbrach. Über
 * `flex: 1` misst der Browser selbst, und es gibt keine Zahl mehr, die
 * veralten kann.
 */
body {
    margin: 0;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    font-family: var(--font);
    font-size: .9375rem;
    line-height: 1.55;
    color: var(--c-text);
    background: var(--c-bg);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3 {
    line-height: 1.25;
    margin: 0 0 .5em;
    letter-spacing: -.011em;
    text-wrap: balance;
}

h1 { font-size: 1.5rem; font-weight: 650; }
h2 { font-size: 1.125rem; font-weight: 620; }
h3 { font-size: 1rem; font-weight: 600; }

p { text-wrap: pretty; }

a { color: var(--c-accent); text-decoration-thickness: 1px; text-underline-offset: .15em; }

.muted { color: var(--c-text-muted); }

/* Zahlen, die untereinander stehen, brauchen feste Ziffernbreite — sonst
   wandern die Spalten von Zeile zu Zeile. */
.table td, .table th, .tabular { font-variant-numeric: tabular-nums; }

/* Ein Symbol nimmt Groesse und Farbe seiner Umgebung an. */
.icon {
    width: 1em;
    height: 1em;
    flex: none;
    vertical-align: -.14em;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* ---------- Grundgeruest ---------- */

.site-header {
    flex: none;
    display: flex;
    align-items: center;
    gap: .35rem;
    height: var(--header-h);
    padding: 0 1rem;
    background: var(--c-surface);
    border-bottom: 1px solid var(--c-border);
}

.site-brand {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    margin-right: .75rem;
    padding: .3rem .4rem;
    font-weight: 640;
    letter-spacing: -.01em;
    color: var(--c-text);
    text-decoration: none;
    border-radius: var(--radius-sm);
}

.site-brand__text {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.site-brand__name { line-height: 1.15; }

/* Der systemweite Text unter dem Namen. Er darf die Kopfzeile nicht hoeher
   machen — deshalb enge Zeilenhoehe und kein Umbruch: Passt er nicht, wird er
   abgeschnitten statt die Zeile zu sprengen. */
.site-brand__claim {
    max-width: 14rem;
    overflow: hidden;
    font-size: .72rem;
    font-weight: 450;
    line-height: 1.15;
    color: var(--c-text-muted);
    letter-spacing: 0;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------- Die Bildmarke ---------- */

.logo { flex: none; display: block; }

.logo__tile { fill: var(--c-accent); }

/* Die drei Balken stehen fuer die Spalten. Nach rechts blasser: Das gibt der
   Marke Tiefe, ohne dass sie bei 22 px in Einzelteile zerfaellt. */
.logo__bar { fill: #fff; }
.logo__bar--2 { opacity: .82; }
.logo__bar--3 { opacity: .62; }

.logo--large .logo__tile { filter: drop-shadow(0 6px 14px rgb(47 111 237 / .35)); }

.site-nav { display: flex; align-items: center; gap: .15rem; }

.site-nav a {
    padding: .35rem .6rem;
    font-size: .9rem;
    color: var(--c-text-muted);
    text-decoration: none;
    border-radius: var(--radius-sm);
    transition: color var(--t), background var(--t);
}

.site-nav a:hover { color: var(--c-text); background: var(--c-surface-alt); }
.site-nav a[aria-current="page"] { color: var(--c-text); font-weight: 550; background: var(--c-surface-alt); }

/* ---------- Suche im Seitenkopf ---------- */

/* Das Suchfeld nimmt den Platz zwischen Menü und rechter Gruppe ein — und gibt
   ihn wieder her, wenn es eng wird. Ohne `min-width: 0` und `shrink` bestünde
   es auf seiner Breite: Als die beiden Rückgängig-Pfeile hinzukamen, lief der
   Kopf dadurch um 16 Pixel über den Fensterrand hinaus und zog die ganze Seite
   in die Breite. */
.site-search {
    position: relative;
    display: flex;
    align-items: center;
    flex: 0 1 auto;
    min-width: 0;
    margin-left: auto;
    margin-right: .5rem;
}

/* Es darf schmaler werden als seine 13 rem, aber nicht beliebig: Ohne
   Untergrenze schrumpfte es auf 77 Pixel — ein Feld, in dem kein Suchbegriff
   mehr zu sehen ist. Neun rem sind die Grenze, ab der es noch etwas taugt. */
.site-search input { min-width: 9rem; }

/* Die rechte Gruppe schrumpft nicht: Knöpfe, die schmaler werden, sind
   schlechter zu treffen. Sie behält ihre Breite, das Suchfeld gibt nach. */
.site-user { flex: none; }

/* Der Umschalter der Hilfe und ihre Box liegen in einem gemeinsamen Element,
   damit der Stimulus-Controller beide erreicht. Als Blockelement wurde es
   allerdings 181 Pixel hoch — die Box darin ist zwar `position: fixed` und
   verborgen, trug ihre Höhe aber trotzdem nach außen. Auf einem Telefon zog
   das den ganzen Seitenkopf auf 428 Pixel auf, also über eine halbe
   Bildschirmhöhe. Als `inline-flex` ist das Element so hoch wie sein Knopf. */
.help {
    display: inline-flex;
    align-items: center;
}

.site-search .icon {
    position: absolute;
    left: .55rem;
    font-size: .95rem;
    color: var(--c-text-muted);
    pointer-events: none;
}

.site-search input {
    width: 13rem;
    height: 2rem;
    padding: 0 .6rem 0 2rem;
    font: inherit;
    font-size: .875rem;
    color: var(--c-text);
    background: var(--c-surface-alt);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    transition: width var(--t), background var(--t), border-color var(--t), box-shadow var(--t);
}

.site-search input::placeholder { color: var(--c-text-muted); }

/* Beim Schreiben wird das Feld breiter. Ein Suchbegriff ist oft länger als
   die Ruhebreite, und ein Feld, in dem man den eigenen Text nicht mehr sieht,
   ist ärgerlicher als eines, das kurz Platz einnimmt. */
.site-search input:focus-visible {
    width: 20rem;
    outline: none;
    background: var(--c-surface);
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-ring);
}

.site-user {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.site-user__link {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .25rem .45rem .25rem .25rem;
    text-decoration: none;
    border-radius: var(--radius-pill);
    transition: background var(--t);
}

.site-user__link:hover { background: var(--c-surface-alt); }
.site-user__link:hover .site-user__name { color: var(--c-text); }
.site-user__link[aria-current="page"] { background: var(--c-surface-alt); }

.site-user__link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--c-ring);
}

.site-user__name { color: var(--c-text-muted); font-size: .9rem; transition: color var(--t); }

/* Der Hinweis auf ein veraltetes Schema. Er steht über dem Inhalt und außerhalb
   von .site-main, damit er auch auf dem Board erscheint, dessen Hauptbereich
   nicht mitrollt. */
.schema-warning {
    flex: none;
    margin: 0;
    padding: .65rem 1rem;
    font-size: .875rem;
    color: var(--c-warning);
    background: var(--c-warning-soft);
    border-bottom: 1px solid color-mix(in srgb, var(--c-warning) 35%, transparent);
}

.schema-warning a { color: inherit; font-weight: 600; }

.site-main {
    flex: 1 1 auto;
    min-height: 0;
    padding: 1.5rem;
}

.page { max-width: 62rem; }
.page__title { margin-bottom: .75rem; }

body.page-centered .site-main {
    display: grid;
    place-items: center;
    padding: 1.5rem;
}

/* ---------- Bausteine ---------- */

.avatar {
    display: inline-grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--c-accent-soft);

    /* Nicht --c-accent: Das ergibt auf dem hellblauen Grund nur 3,94:1 und
       reisst damit die Grenze von 4,5:1 fuer Text. Der dunklere Ton kommt auf
       5,36:1. Dieselbe Ueberlegung gilt fuer .flash--info weiter unten. */
    color: var(--c-accent-strong);
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .01em;
    flex: none;
    user-select: none;
}

.avatar--small { width: 22px; height: 22px; font-size: .6rem; }

/* Ein hochgeladenes Profilbild füllt denselben Kreis wie die Initialen.
   `object-fit: cover` schneidet zu, statt zu verzerren — ein in die Breite
   gezogenes Gesicht wäre schlimmer als ein angeschnittenes. */
.avatar--photo {
    object-fit: cover;
    background: var(--c-surface-alt);
}

/* Muss nach .avatar stehen: Beide sind einfache Klassen, bei gleicher
   Spezifität gewinnt die spätere Regel. */
.avatar--large { width: 46px; height: 46px; font-size: 1.05rem; }

/* ---------- Bild groß anzeigen ---------- */

.avatar--zoom { cursor: zoom-in; }

.avatar--zoom:hover {
    box-shadow: 0 0 0 3px var(--c-ring);
}

/* Der Dialog selbst ist nur der Rahmen: durchsichtig, ohne Rand, im Raum
   zentriert. Sichtbar sind allein Bild und Beschriftung. */
.lightbox {
    max-width: min(90vw, 40rem);
    max-height: 90vh;
    padding: 0;
    color: #fff;
    background: none;
    border: none;
    overflow: visible;
}

.lightbox::backdrop {
    background: rgb(9 12 18 / .78);
    backdrop-filter: blur(2px);
}

.lightbox__image {
    display: block;
    max-width: 100%;
    max-height: 78vh;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-3);
    cursor: zoom-out;
}

.lightbox__caption {
    margin: .75rem 0 0;
    font-size: .9rem;
    text-align: center;
    text-shadow: 0 1px 3px rgb(0 0 0 / .6);
}

.card {
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-2);
    padding: 1.5rem;
}

.card--narrow { width: min(23rem, 100%); padding: 1.75rem; }
.card__title { margin-bottom: 1.25rem; }

/* Der Fussbereich einer schmalen Karte: die Nebenwege unter dem Knopf —
   "Passwort vergessen?", "Zurueck zur Anmeldung". Abgesetzt und kleiner,
   damit sie neben dem Hauptknopf nicht um Aufmerksamkeit streiten. */
.card__foot {
    margin: 1.1rem 0 0;
    font-size: .9rem;
    text-align: center;
}

.flash {
    display: flex;
    gap: .55rem;
    margin: 0 0 1rem;
    padding: .65rem .85rem;
    font-size: .9rem;
    border-radius: var(--radius);
    border: 1px solid;
}

.flash--error   { background: var(--c-danger-soft);  border-color: color-mix(in srgb, var(--c-danger) 35%, transparent);  color: var(--c-danger); }
.flash--success { background: var(--c-success-soft); border-color: color-mix(in srgb, var(--c-success) 35%, transparent); color: var(--c-success); }
.flash--info    { background: var(--c-accent-soft);  border-color: color-mix(in srgb, var(--c-accent) 35%, transparent);  color: var(--c-accent-strong); }

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

/* Jedes Feld traegt seinen eigenen Abstand nach unten — auch das letzte. Sonst
   klebt auf der Anmeldeseite, wo direkt hinter dem letzten Feld die
   Schaltflaeche steht, beides aneinander. Der Abstand der Schaltflaechenzeile
   ist entsprechend knapp gehalten. */
.field { margin-bottom: 1.1rem; }

.field__label,
.field > label {
    display: block;
    margin-bottom: .3rem;
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .005em;
    color: var(--c-text);
}

/* Pflichtfelder erhalten keinen Stern. Stattdessen ist die Ausnahme
   gekennzeichnet — in diesen Formularen sind die meisten Felder Pflicht, ein
   Stern an fast jeder Zeile sagt nichts mehr aus. */

.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="date"],
.field input[type="time"],
.field input[type="number"],
.field input[type="search"],
.field input[type="url"],
.field input[type="color"],
.field select,
.field textarea {
    width: 100%;
    min-height: var(--control-h);
    padding: .45rem .65rem;
    font: inherit;
    color: var(--c-text);
    background: var(--c-surface);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius);
    box-shadow: inset 0 1px 1px rgb(16 24 40 / .04);
    transition: border-color var(--t), box-shadow var(--t);
}

.field textarea { min-height: 7rem; resize: vertical; line-height: 1.55; }
.field input[type="color"] { padding: .2rem; height: var(--control-h); cursor: pointer; }

.field input::placeholder,
.field textarea::placeholder { color: var(--c-text-muted); opacity: .85; }

.field input:hover,
.field select:hover,
.field textarea:hover { border-color: var(--c-text-muted); }

/* Ein Ring aus box-shadow statt outline: Er folgt der Rundung des Feldes und
   wird von keinem Elternteil mit overflow abgeschnitten. */
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-ring);
}

.field--invalid input,
.field--invalid select,
.field--invalid textarea { border-color: var(--c-danger); }

.field--invalid input:focus-visible,
.field--invalid select:focus-visible,
.field--invalid textarea:focus-visible {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-danger) 30%, transparent);
}

.field input:disabled,
.field select:disabled,
.field textarea:disabled {
    background: var(--c-surface-sunk);
    color: var(--c-text-muted);
    cursor: not-allowed;
}

.field__help {
    display: block;
    margin: .35rem 0 0;
    font-size: .8125rem;
    line-height: 1.45;
    color: var(--c-text-muted);
    max-width: 62ch;
}

.field__errors {
    margin: .35rem 0 0;
    padding: 0;
    list-style: none;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--c-danger);
}

/* Kontrollkaestchen */

.field--check .field__check-line,
.field--check {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.field--check { flex-wrap: wrap; }
.field--check .field__check-line { flex: 1 1 100%; }

.field--check .field__label,
.field--check label {
    margin: 0;
    font-weight: 400;
    color: var(--c-text);
    cursor: pointer;
}

.field--check .field__help,
.field--check .field__errors { flex: 1 1 100%; margin-left: 1.6rem; }

input[type="checkbox"],
input[type="radio"] {
    width: 1.05rem;
    height: 1.05rem;
    margin: 0;
    accent-color: var(--c-accent);
    flex: none;
    cursor: pointer;
}

input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--c-ring);
    border-radius: 3px;
}

/* ---------- Farbauswahl ---------- */

.colorpicker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem;
}

.colorpicker__swatches {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

/*
 * Eine Kachel ist ein quadratischer Knopf in der Farbe, die sie meint. Die
 * Auswahl wird über einen Ring *außerhalb* der Fläche angezeigt statt über
 * einen Rahmen darin: Ein Rahmen frisst von der Farbe, und gerade bei dunklen
 * Tönen sieht man dann nicht mehr, welche Farbe man eigentlich gewählt hat.
 */
.colorpicker__swatch {
    width: 26px;
    height: 26px;
    padding: 0;
    background: var(--swatch);
    border: 1px solid rgb(0 0 0 / .18);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: transform var(--t), box-shadow var(--t);
}

.colorpicker__swatch:hover { transform: translateY(-1px); }

.colorpicker__swatch.is-selected {
    box-shadow: 0 0 0 2px var(--c-surface), 0 0 0 4px var(--c-text);
}

.colorpicker__swatch:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--c-surface), 0 0 0 5px var(--c-ring);
}

.colorpicker__custom {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding-left: .75rem;
    border-left: 1px solid var(--c-border);
}

.colorpicker__wheel {
    display: inline-grid;
    place-items: center;
    cursor: pointer;
}

/* Der native Farbwähler sieht in jedem Browser anders aus. Er bekommt deshalb
   dieselbe Größe und Rundung wie eine Kachel, damit die Reihe nicht mit einem
   Fremdkörper endet. */
.colorpicker__wheel input[type="color"] {
    width: 26px;
    height: 26px;
    padding: 0;
    background: none;
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.colorpicker__wheel input[type="color"]::-webkit-color-swatch-wrapper { padding: 2px; }
.colorpicker__wheel input[type="color"]::-webkit-color-swatch { border: none; border-radius: 3px; }

.colorpicker__readout {
    font-family: var(--font-mono);
    font-size: .8125rem;
    color: var(--c-text-muted);
    letter-spacing: .02em;
}

/* ---------- Hintergrundauswahl ---------- */

.bg-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
    gap: .5rem;
    margin-bottom: 1rem;
}

/* Überschrift einer Gruppe von Hintergründen. Mehr Abstand darüber als
   darunter — sie gehört zu den Kacheln, die folgen. */
.bg-group__title {
    margin: 1rem 0 .5rem;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--c-text-muted);
}

.bg-group__title:first-child { margin-top: .25rem; }

.bg-group__note {
    margin-left: .5rem;
    font-weight: 400;
    font-size: .78rem;
}

/* Fotos bekommen ein breiteres Raster: Bei einer Landschaft in Briefmarkengröße
   erkennt man nichts, und man wählt sie ja nach dem Motiv. */
.bg-picker--photos { grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); }
.bg-picker--photos .bg-option__probe { height: 4.5rem; }

.credits-thumb {
    display: block;
    width: 80px;
    height: 50px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    border: 1px solid var(--c-border);
}

/* Der Auswahlknopf selbst ist unsichtbar; die Kachel ist die Bedienung. Er
   bleibt aber im Baum, damit Tastatur und Vorlesegeräte ihn finden. */
.bg-option {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: .3rem;
    cursor: pointer;
}

.bg-option input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.bg-option__probe {
    display: block;
    height: 3.25rem;
    overflow: hidden;
    border: 1px solid rgb(0 0 0 / .18);
    border-radius: var(--radius);
    transition: box-shadow var(--t), transform var(--t);
}

/* Die Fotokacheln sind seit 1.12.0 echte <img> statt CSS-Hintergründe — nur so
   greift `loading="lazy"`, und bei achtzig Kacheln lädt der Browser dann bloß,
   was im Sichtfeld steht. Das Bild füllt die Kachel wie zuvor der Hintergrund. */
.bg-option__probe img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.bg-option:hover .bg-option__probe { transform: translateY(-1px); }

.bg-option.is-selected .bg-option__probe,
.bg-option input:checked + .bg-option__probe {
    box-shadow: 0 0 0 2px var(--c-surface), 0 0 0 4px var(--c-text);
}

.bg-option input:focus-visible + .bg-option__probe {
    box-shadow: 0 0 0 2px var(--c-surface), 0 0 0 5px var(--c-ring);
}

.bg-option__name { font-size: .8125rem; color: var(--c-text-muted); }

/* ---------- Profilbild ---------- */

.avatar-edit {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
}

.avatar-edit .field { flex: 1; margin-bottom: 0; }

.field input[type="file"] {
    width: 100%;
    font: inherit;
    font-size: .875rem;
    color: var(--c-text-muted);
}

.field input[type="file"]::file-selector-button {
    margin-right: .6rem;
    padding: .35rem .7rem;
    font: inherit;
    font-size: .8125rem;
    font-weight: 550;
    color: var(--c-text);
    background: var(--c-surface-alt);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

/* ---------- Suchergebnisse ---------- */

.search-form {
    display: flex;
    align-items: flex-end;
    gap: .75rem;
    margin-bottom: 1.5rem;
}

.search-form .field { flex: 1; margin-bottom: 0; }

.search-form input[type="search"] {
    width: 100%;
    min-height: var(--control-h);
    padding: .45rem .65rem;
    font: inherit;
    color: var(--c-text);
    background: var(--c-surface);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius);
}

.search-form input[type="search"]:focus-visible {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-ring);
}

.search-count { margin: 0 0 1.25rem; }

.search-group {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin: 1.75rem 0 .6rem;
    font-size: .8125rem;
    font-weight: 650;
    letter-spacing: .01em;
    color: var(--c-text-muted);
}

.search-list { list-style: none; margin: 0; padding: 0; }

.search-hit {
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius);
    margin-bottom: .4rem;
    transition: border-color var(--t), box-shadow var(--t);
}

.search-hit:hover { border-color: var(--c-border-strong); box-shadow: var(--shadow-1); }

.search-hit__link {
    display: block;
    padding: .7rem .9rem;
    color: inherit;
    text-decoration: none;
    border-radius: inherit;
}

.search-hit__link:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--c-ring); }

.search-hit__title {
    display: block;
    font-weight: 600;
    margin-bottom: .15rem;
}

.search-hit__excerpt {
    display: block;
    font-size: .875rem;
    color: var(--c-text-muted);
    margin-bottom: .3rem;
}

.search-hit__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .6rem;
    font-size: .8125rem;
    color: var(--c-text-muted);
}

.search-hit__project { display: inline-flex; align-items: center; gap: .35rem; }

/* Die Fundstelle wird markiert, nicht eingefärbt: `mark` sagt Vorlesegeräten,
   dass hier etwas hervorgehoben ist, eine Farbe allein sagt gar nichts. */
mark {
    padding: 0 .1em;
    color: inherit;
    background: color-mix(in srgb, var(--c-warning) 32%, transparent);
    border-radius: 2px;
}

/* ---------- CSV-Import ---------- */

.import-example {
    margin: 0 0 1rem;
    padding: .8rem .9rem;
    overflow-x: auto;
    font-family: var(--font-mono);
    font-size: .8125rem;
    line-height: 1.6;
    color: var(--c-text);
    background: var(--c-surface-sunk);
    border-radius: var(--radius);
}

.import-skipped {
    margin: 0;
    padding-left: 1.2rem;
    font-size: .875rem;
    color: var(--c-warning);
}

/* ---------- Schieberegler mit Wertanzeige ---------- */

.field input[type="range"] {
    width: 100%;
    max-width: 22rem;
    accent-color: var(--c-accent);
    cursor: pointer;
}

.field input[type="range"]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--c-ring);
    border-radius: var(--radius);
}

.rangeout {
    display: inline-block;
    margin-left: .6rem;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: .8125rem;
    color: var(--c-text);
}

/* ---------- Schaltflaechen ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    min-height: var(--control-h);
    padding: 0 .85rem;
    font: inherit;
    font-size: .9rem;
    font-weight: 550;
    white-space: nowrap;
    color: var(--c-text);
    background: var(--c-surface);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow-1);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--t), border-color var(--t), box-shadow var(--t), transform var(--t);
}

.btn:hover { background: var(--c-surface-alt); border-color: var(--c-text-muted); }
.btn:active { transform: translateY(1px); box-shadow: none; }

.btn:focus-visible {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-ring);
}

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: .55;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.btn--primary {
    background: var(--c-accent);
    border-color: var(--c-accent);
    color: var(--c-accent-text);
}

.btn--primary:hover { background: var(--c-accent-strong); border-color: var(--c-accent-strong); }

.btn--ghost {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    color: var(--c-text-muted);
}

.btn--ghost:hover { color: var(--c-text); background: var(--c-surface-alt); border-color: transparent; }

.btn--block { width: 100%; }
.btn--small { min-height: 1.75rem; padding: 0 .55rem; font-size: .8125rem; }

.btn--danger {
    background: var(--c-danger);
    border-color: var(--c-danger);
    color: #fff;
}

.btn--danger:hover { background: color-mix(in srgb, var(--c-danger) 85%, #000); border-color: transparent; }

/* Für den Rückweg aus einem fremden Konto. Auffällig, aber nicht rot: Es ist
   kein gefährlicher Griff, sondern einer, den man leicht vergisst. */
.btn--warn {
    background: var(--c-warning);
    border-color: var(--c-warning);
    color: #fff;
}

.btn--warn:hover { background: color-mix(in srgb, var(--c-warning) 85%, #000); border-color: transparent; }

/* Der Streifen, solange jemand in fremdem Konto steckt.

   Klebt unter der Kopfzeile und scrollt nicht weg — wer eine Viertelstunde als
   jemand anders unterwegs ist, vergisst es sonst und schreibt einen Kommentar
   in fremdem Namen. */
.impersonation {
    position: sticky;
    top: var(--header-h);
    z-index: 40;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: .25rem 1rem;
    padding: .45rem 1rem;
    font-size: .875rem;
    color: #fff;
    background: var(--c-warning);
    box-shadow: 0 1px 4px rgb(0 0 0 / .18);
}

.impersonation a {
    color: #fff;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: .18em;
}

@media (max-width: 640px) {
    .impersonation { font-size: .8125rem; padding: .4rem .6rem; }
}

@media (prefers-color-scheme: dark) {

:root:not([data-theme="light"]) .btn--danger { color: #1a0f0e; }
}

/* Dieselben Werte fuer die ausdrueckliche Wahl „dunkel". Eine
   Medienabfrage laesst sich nicht mit einem Attributselektor verunden,
   deshalb steht der Block zweimal da; erzeugt aus dem Block darueber. */

:root[data-theme="dark"] .btn--danger { color: #1a0f0e; }



/* ---------- Seitenkopf und Listen ---------- */

.page--narrow { max-width: 46rem; }

/* Eine Einstellungsseite mit zwei Spalten.

   Einspaltig stand das Formular als schmaler Streifen in einer halbleeren
   Seite: rechts nichts, unten die Zusatzkarten, die man erst erscrollen
   musste. Links steht jetzt, was die Spalte ausmacht, rechts, was man mit
   ihr tun kann.

   Der Umbruchpunkt liegt bei 68rem und nicht tiefer: Darunter waeren beide
   Spalten so schmal, dass die Auswahlfelder und die Hilfetexte in
   Wortsalat umbrechen. Ein Fenster, das nicht reicht, bekommt lieber
   wieder eine Spalte. */
.page--settings { max-width: 76rem; }

.settings-grid { display: grid; gap: var(--gap); align-items: start; }

@media (min-width: 68rem) {
    .settings-grid { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
}

/* Die rechte Spalte stapelt ihre Karten und waechst nicht in die Hoehe der
   linken: `align-content: start` haelt sie oben, sonst zoege die letzte
   Karte ihren Rand bis zum Fuss des Formulars. */
.settings-grid__main,
.settings-grid__side {
    display: grid;
    gap: var(--gap);
    align-content: start;
    min-width: 0;
}

/* In der Karte steckt der Abstand schon; ein zweiter Aussenabstand ergaebe
   im Gitter doppelte Luecken. */
.settings-grid .card { margin-bottom: 0; }

.page__head {
    display: flex;
    align-items: center;
    gap: var(--gap);
    margin-bottom: 1.25rem;
}

.page__head .page__title { margin: 0; }
.page__actions { margin-left: auto; display: flex; gap: .5rem; }

/* Das X oben rechts an einer Einstellungsseite.

   Dieselbe Stelle wie in jedem Dialog. Es ersetzt den "Abbrechen"-Knopf
   unten nicht, sondern ergaenzt ihn: Wer oben ist, klickt oben; wer bis zum
   Formularende gescrollt ist, klickt dort. */
.page__close {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    margin-left: auto;
    font-size: 1.1rem;
    /* Die Farbe des Kopfes, nicht die des Fliesstextes: Auf einem Projekt
       mit farbigem Hintergrund steht die Ueberschrift hell da, und ein
       gedaempftes Grau daneben waere darauf kaum zu sehen. So ist das X
       immer so gut sichtbar wie der Titel, neben dem es steht. */
    color: inherit;
    opacity: .65;
    border: 1px solid transparent;
    border-radius: var(--radius);
    transition: background-color .12s, opacity .12s, border-color .12s;
}

.page__close:hover,
.page__close:focus-visible {
    opacity: 1;
    background: var(--c-surface-2);
    border-color: var(--c-border);
}

/* Ein aufklappbarer Hinweis.

   Fuer Erklaerungen, die beim ersten Mal wichtig sind und danach nie wieder.
   Ausgeschrieben nahmen sie mehr Platz ein als das Formular, zu dem sie
   gehoeren, und drueckten die uebrigen Einstellungen aus dem Bild.

   Ohne JavaScript: <details> kann das von Haus aus, samt Tastaturbedienung
   und Suchfunktion des Browsers. */
.hinweis { margin-top: 1rem; }

/* Die Anzeigeart von <summary> bleibt unangetastet.

   Ein `display: inline-flex` darauf nimmt dem Element seine Sonderrolle:
   Das <details> klappt dann nicht mehr zu, die Absaetze stehen dauerhaft da
   — und zwar ohne jede Fehlermeldung. Gemessen im Pruefstand: `open` war
   false, die Absaetze trotzdem hoch. Ausgerichtet wird deshalb ueber
   `::before` statt ueber Flex. */
.hinweis > summary {
    padding: .2rem 0;
    font-size: .9rem;
    color: var(--c-text-muted);
    cursor: pointer;
    list-style: none;
}

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

/* Ein eigenes Dreieck statt des Browserzeichens: Jeder Browser zeichnet ein
   anderes, und in der Zeile darunter stuenden sie verschieden weit ein. */
.hinweis > summary::before {
    content: "";
    display: inline-block;
    width: 0;
    height: 0;
    margin-right: .4rem;
    border: .3rem solid transparent;
    border-left-color: currentColor;
    transition: transform .12s;
}

.hinweis[open] > summary::before { transform: rotate(90deg) translateX(-.05rem); }

.hinweis > summary:hover { color: var(--c-text); }

.hinweis > p { margin: .6rem 0 0; font-size: .9rem; }

/* ---------- Reiter innerhalb einer Seite ---------- */

/* Es sind gewoehnliche Verweise, keine geskripteten Umschalter: Jeder Reiter
   hat seine eigene Adresse und laesst sich einzeln aufrufen, verschicken und
   mit dem Zurueck-Knopf verlassen. */
.tabs {
    display: flex;
    gap: .25rem;
    margin-bottom: 1.25rem;
    border-bottom: 1px solid var(--c-border);
}

.tabs__tab {
    padding: .5rem .9rem;
    font-size: .925rem;
    color: var(--c-text-muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color var(--t), border-color var(--t);
}

.tabs__tab:hover { color: var(--c-text); }

.tabs__tab[aria-current="page"] {
    font-weight: 550;
    color: var(--c-accent);
    border-bottom-color: var(--c-accent);
}

.empty {
    padding: 3rem 2rem;
    text-align: center;
    color: var(--c-text-muted);
    background: var(--c-surface);
    border: 1px dashed var(--c-border-strong);
    border-radius: var(--radius-lg);
}

.empty p { margin: 0 0 .75rem; max-width: 44ch; margin-inline: auto; }
.empty .btn { color: var(--c-text); }

.project-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: var(--gap);
}

.project-card {
    display: flex;
    flex-direction: column;
    padding: 1.1rem;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-1);
    transition: border-color var(--t), box-shadow var(--t), transform var(--t);
}

.project-card:hover {
    border-color: var(--c-border-strong);
    box-shadow: var(--shadow-2);
    transform: translateY(-1px);
}

.project-card__link { color: inherit; text-decoration: none; }

/* Die Projektfarbe sitzt als Punkt neben dem Namen statt als Balken am Rand.
   Derselbe Punkt steht im Untermenue des Projekts — dieselbe Sache, dieselbe
   Form. */
.project-card__name {
    display: flex;
    align-items: center;
    gap: .45rem;
    margin: 0 0 .35rem;
    font-size: 1rem;
}

.project-card__name::before {
    content: "";
    width: 9px;
    height: 9px;
    flex: none;
    border-radius: 50%;
    background: var(--project-color, var(--c-accent));
}

.project-card__desc { margin: 0; color: var(--c-text-muted); font-size: .875rem; }
.project-card__meta { margin: .6rem 0 .75rem; font-size: .8125rem; }

.project-card__actions {
    margin-top: auto;
    display: flex;
    gap: .35rem;
}

/* ---------- Untermenue eines Projekts ---------- */

.subnav {
    display: flex;
    align-items: center;
    gap: .9rem;
    padding: 0 1rem;
    height: 2.75rem;
    background: var(--c-surface);
    border-bottom: 1px solid var(--c-border);
}

.page .subnav {
    margin: -1.5rem -1.5rem 1.5rem;
    border-radius: 0;
}

.subnav__project {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    margin-right: .35rem;
    font-weight: 620;
}

.subnav__dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--project-color, var(--c-accent));
}

.subnav__link {
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 100%;
    font-size: .9rem;
    color: var(--c-text-muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    transition: color var(--t), border-color var(--t);
}

.subnav__link:hover { color: var(--c-text); }
.subnav__link.is-active { color: var(--c-text); font-weight: 550; border-bottom-color: var(--c-accent); }

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

.table {
    width: 100%;
    margin-bottom: 1.5rem;
    border-collapse: separate;
    border-spacing: 0;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.table th,
.table td {
    padding: .7rem .85rem;
    text-align: left;
    border-bottom: 1px solid var(--c-border);
    vertical-align: middle;
}

.table th {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--c-text-muted);
    background: var(--c-surface-alt);
    white-space: nowrap;
}

.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr { transition: background var(--t); }
.table tbody tr:hover { background: var(--c-surface-alt); }
.table td .avatar { margin-right: .4rem; vertical-align: middle; }
/* Der Selektor braucht das führende `.table`: `.table th, .table td` oben ist
   spezifischer als eine Klasse allein und würde die Ausrichtung sonst wieder
   nach links ziehen. */
.table .table__actions { text-align: right; white-space: nowrap; }

/* ---------- Formularvarianten ---------- */

.inline-form { display: inline; }

.inline-form select {
    height: 1.9rem;
    padding: 0 .4rem;
    font: inherit;
    font-size: .8125rem;
    color: var(--c-text);
    background: var(--c-surface);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius-sm);
}

.row-form {
    display: flex;
    align-items: flex-end;
    gap: .75rem;
    flex-wrap: wrap;
}

.row-form .field { margin-bottom: 0; flex: 1 1 12rem; }

/* Zwischenüberschrift innerhalb eines Formulars. Mehr Abstand darüber als
   darunter — sie gehört zu dem, was folgt, nicht zu dem, was davor stand. */
.form-section {
    margin: 1.75rem 0 .9rem;
    padding-top: 1.25rem;
    font-size: .8125rem;
    font-weight: 650;
    letter-spacing: .02em;
    color: var(--c-text-muted);
    border-top: 1px solid var(--c-border);
}

.form-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-top: .4rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--c-border);
}

.card--danger { margin-top: 1.5rem; border-color: color-mix(in srgb, var(--c-danger) 40%, var(--c-border)); }
.card--danger h2 { font-size: 1rem; color: var(--c-danger); }

.role-help { margin: 1rem 0 0; font-size: .875rem; }
.role-help dt { font-weight: 600; margin-top: .5rem; }
.role-help dd { margin: 0; color: var(--c-text-muted); }

/* ---------- Was welche Rolle darf ---------- */

/* Die Tabelle steht in einer Karte und braucht deshalb keinen eigenen Rand;
   der doppelte Rahmen sähe nach Kasten im Kasten aus. */
.role-matrix .table { margin-bottom: 0; border: 0; background: none; }
.role-matrix .table tr:last-child th,
.role-matrix .table tr:last-child td { border-bottom: 0; }

.role-matrix__caption {
    padding-bottom: .5rem;
    font-size: .8125rem;
    font-weight: 600;
    text-align: left;
    color: var(--c-text-muted);
}

.table--compact th,
.table--compact td { padding: .45rem .6rem; }

/* Die erste Spalte trägt den Handgriff und darf umbrechen; die drei
   Rollenspalten sind schmal und gleich breit, damit die Häkchen untereinander
   stehen und die Zeile mit einem Blick lesbar bleibt. */
.role-matrix .table th[scope="row"] { font-weight: 400; white-space: normal; }
.role-matrix__cell { width: 5.5rem; text-align: center !important; }

.role-matrix__yes { font-weight: 700; color: var(--c-success); }
.role-matrix__no { color: var(--c-text-muted); }

.role-matrix__note { margin: 1rem 0 0; font-size: .875rem; }

/* Auf schmalen Geräten scrollt .table waagerecht und setzt dafür
   `white-space: nowrap`. Für diese Tabelle wäre das falsch: Ihre erste Spalte
   besteht aus ganzen Sätzen, die dann eine einzige lange Zeile ergäben. Sie
   darf stattdessen umbrechen — vier schmale Spalten passen auch auf ein
   Telefon. */
@media (max-width: 640px) {
    .role-matrix .table { display: table; white-space: normal; }
    .role-matrix__cell { width: 3.5rem; }
    .table--compact th,
    .table--compact td { padding: .4rem .35rem; font-size: .8125rem; }
}

/* ---------- Benutzerverwaltung ---------- */

/* Ein einmalig angezeigtes Passwort muss auffallen — es ist nach dem
   Weiterklicken unwiederbringlich weg. Deshalb eine eigene Farbe statt des
   üblichen Grüns, und die Zeichen in einer Schrift mit fester Breite, damit
   sich Null und O unterscheiden lassen. */
.flash--password {
    background: var(--c-warning-soft);
    border-color: color-mix(in srgb, var(--c-warning) 45%, transparent);
    color: var(--c-warning);
    font-family: var(--font-mono);
    font-size: .9rem;
    letter-spacing: .01em;
    word-break: break-word;
}

.flash--password strong { font-family: var(--font); }

.table tr.is-inactive td { color: var(--c-text-muted); }
.table tr.is-inactive .avatar { filter: grayscale(1); opacity: .7; }

.badge-off {
    display: inline-block;
    padding: .05rem .45rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--c-text-muted);
    background: var(--c-surface-sunk);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius-pill);
}

.table__actions form + form { margin-left: .25rem; }

/* ---------- Glocke ---------- */

/*
 * 32 Pixel waren zu klein. Die Glocke ist ein Ziel, das man mit der Maus
 * trifft oder eben nicht; auf einem Berührungsbildschirm liegt die übliche
 * Untergrenze bei 44 Pixeln. Das Symbol wächst mit, sonst schwimmt es in der
 * größeren Fläche. Dasselbe Maß trägt das Fragezeichen daneben
 * (`.help-toggle` in help.css).
 */
/* ---------- Rückgängig und Wiederherstellen ---------- */

/* Zwei Formulare nebeneinander, die aussehen sollen wie ein Paar Knöpfe. Ohne
   `display: flex` am Umschlag stünden sie untereinander — ein <form> ist ein
   Blockelement. */
.undo { display: flex; gap: .15rem; }

.undo__btn {
    display: inline-grid;
    place-items: center;
    width: 2.4rem;
    height: 2.75rem;
    font-size: 1.35rem;
    color: var(--c-text-muted);
    background: none;
    border: 0;
    border-radius: var(--radius);
    cursor: pointer;
    transition: color var(--t), background var(--t);
}

.undo__btn:hover:not(:disabled) { color: var(--c-text); background: var(--c-surface-alt); }

/* Ein ruhender Knopf bleibt stehen und wird blass, statt zu verschwinden: Ein
   Kopf, in dem Knöpfe kommen und gehen, verschiebt bei jedem Klick die
   Nachbarn. Der Zeiger zeigt dabei die Vorgabe, kein „verboten" — es ist
   schlicht nichts zu tun. */
.undo__btn:disabled { opacity: .32; cursor: default; }

.bell {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    font-size: 1.35rem;
    color: var(--c-text-muted);
    text-decoration: none;
    border-radius: var(--radius);
    transition: color var(--t), background var(--t);
}

.bell:hover { color: var(--c-text); background: var(--c-surface-alt); }

.bell__count {
    position: absolute;
    top: 1px;
    right: 0;
    min-width: 16px;
    padding: 0 4px;
    font-size: .625rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    color: #fff;
    background: var(--c-danger);
    border: 2px solid var(--c-surface);
    border-radius: var(--radius-pill);
}

.notification-list { list-style: none; margin: 0; padding: 0; }

.notification {
    display: flex;
    align-items: flex-start;
    gap: .65rem;
    padding: .8rem .95rem;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius);
    margin-bottom: .4rem;
}

/* Ungelesenes traegt einen Punkt vor dem Text — dieselbe Marke wie ueberall
   sonst in der Anwendung, wo etwas Aufmerksamkeit verlangt. */
.notification.is-unread { background: var(--c-accent-soft); border-color: color-mix(in srgb, var(--c-accent) 25%, transparent); }

.notification.is-unread .notification__body::before {
    content: "";
    float: left;
    width: 7px;
    height: 7px;
    margin: .5rem .5rem 0 -.15rem;
    border-radius: 50%;
    background: var(--c-accent);
}

.notification__body { flex: 1; min-width: 0; }
.notification__text { margin: 0 0 .2rem; }
.notification__excerpt { margin: 0 0 .2rem; font-size: .875rem; color: var(--c-text-muted); }
.notification__meta { margin: 0; font-size: .8125rem; }

/* ---------- Agenda ---------- */

.agenda-group { margin-bottom: 1.75rem; }

.agenda-group__title {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin-bottom: .5rem;
    font-size: .8125rem;
    font-weight: 650;
    letter-spacing: .01em;
    color: var(--c-text-muted);
}

.agenda-group__title.is-overdue { color: var(--c-danger); }

.agenda-list { list-style: none; margin: 0; padding: 0; }

.agenda-item {
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius);
    margin-bottom: .4rem;
    transition: border-color var(--t), box-shadow var(--t);
}

.agenda-item:hover { border-color: var(--c-border-strong); box-shadow: var(--shadow-1); }

.agenda-item__link {
    display: block;
    padding: .65rem .85rem;
    color: inherit;
    text-decoration: none;
    border-radius: inherit;
}

.agenda-item__link:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--c-ring); }

.agenda-item__project {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .75rem;
    color: var(--c-text-muted);
}

.agenda-item__title { display: block; margin: .15rem 0; font-weight: 500; }
.agenda-item__meta { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; font-size: .8125rem; color: var(--c-text-muted); }
.text-danger { color: var(--c-danger); font-weight: 600; }

/* ---------- Bericht ---------- */

.report-total { font-size: 1.0625rem; margin: 1rem 0 1.5rem; }

.bar {
    display: inline-block;
    width: 8rem;
    height: 7px;
    vertical-align: middle;
    margin-right: .45rem;
    background: var(--c-surface-sunk);
    border-radius: var(--radius-pill);
    overflow: hidden;
}

.bar__fill { display: block; height: 100%; background: var(--c-accent); border-radius: inherit; }

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------- Schmale Bildschirme ---------- */

@media (max-width: 760px) {
    /* Auf einem Telefon passen Marke, vier Menuepunkte, Glocke, Name und
       Abmelden nicht in eine Zeile — die Seite bekam dadurch einen
       waagerechten Rollbalken. Das Menue rutscht deshalb in eine eigene Zeile
       und rollt dort fuer sich, falls es spaeter mehr Punkte werden. Ein
       Klappmenue waere die andere Loesung, verlangte aber JavaScript fuer
       etwas, das ohne auskommt. */
    .site-header {
        height: auto;
        flex-wrap: wrap;
        gap: .25rem;
        row-gap: .35rem;
        padding: .5rem .65rem;
    }

    .site-brand { margin-right: auto; }
    .site-user { margin-left: 0; }
    .site-user__name { display: none; }

    .site-nav {
        order: 3;
        flex: 1 0 100%;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .site-nav::-webkit-scrollbar { display: none; }
    .site-nav a { padding: .35rem .5rem; white-space: nowrap; }

    /* Auf dem Telefon steht die Suche in der zweiten Zeile neben dem Menü und
       nimmt den Rest der Breite. Ein 13 rem breites Feld neben Marke, Glocke
       und Abmelden ginge dort nicht auf. */
    .site-search {
        order: 4;
        flex: 1 0 100%;
        margin: 0;
    }

    .site-search input,
    .site-search input:focus-visible { width: 100%; }

    .site-main { padding: 1rem; }
    .page .subnav { margin: -1rem -1rem 1rem; }
    .form-actions { flex-wrap: wrap; }

    /* Ueberschrift und Knopfleiste stehen nebeneinander, solange es passt. Bei
       drei Knoepfen wie auf der Projektliste („Archiv", „Import aus Trello
       oder Deck", „Neues Projekt") passt es auf einem Telefon nicht: gemessen
       liefen sie bis 509 Pixel in ein 375 Pixel breites Fenster hinein und
       zogen die ganze Seite mit in die Breite. Sie ruecken deshalb unter die
       Ueberschrift und duerfen dort selbst umbrechen. */
    .page__head { flex-wrap: wrap; }
    .page__actions { margin-left: 0; flex-wrap: wrap; }

    /* Die Unternavigation eines Projekts hat bis zu sechs Eintraege — Board,
       Berichte, Verlauf, Mitglieder, Labels, Einstellungen. Sie rollt fuer
       sich, wie das Hauptmenue darueber, statt die Seite zu verbreitern.
       Umbrechen waere hier falsch: Die Leiste hat eine feste Hoehe und sitzt
       unter dem Kopf, eine zweite Zeile wuerde abgeschnitten. */
    .subnav {
        overflow-x: auto;
        scrollbar-width: none;
    }

    .subnav::-webkit-scrollbar { display: none; }

    .subnav__link,
    .subnav__project { flex: none; white-space: nowrap; }

    /* Eine Labelzeile besteht aus Farbfeld, Namensfeld, „Speichern" und
       „Loeschen". Nebeneinander sind das gemessen 424 Pixel — die einzige
       Seite, die auf dem Telefon tatsaechlich waagerecht rollte. Das
       Namensfeld darf hier schmaler werden, und „Loeschen" ruecht in die
       zweite Zeile, wo es rechts stehen bleibt. */
    .label-admin__form { flex-wrap: wrap; }
    .label-admin__name { flex: 1 1 6rem; min-width: 6rem; }
    .label-admin__row > form:last-child { margin-left: auto; }

    /* Eine Tabelle mit fünf Spalten passt auf kein Telefon. Sie darf für sich
       seitwärts rollen, statt die ganze Seite mitzuziehen. */
    .table { display: block; overflow-x: auto; white-space: nowrap; }
}

/* Auf einem gewoehnlichen Telefon (375 Pixel) brauchten die fuenf Menuepunkte
   zusammen 379 Pixel — der letzte, „System", war um 25 Pixel angeschnitten.
   Rollen liesse sich das Menue zwar, aber ein angeschnittener Eintrag sieht
   nach Fehler aus, und man muesste ihn erst hervorschieben. Eine engere
   Polsterung bringt 40 Pixel und damit alle fuenf ins Bild; die Hoehe der
   Trefferflaeche bleibt unveraendert. Das Rollen aus dem Block darueber bleibt
   als Auffangnetz, falls einmal ein Punkt hinzukommt. */
@media (max-width: 480px) {
    .site-nav a { padding-left: .25rem; padding-right: .25rem; }
}

/* Die Liste der eigenen Bilder im Bildnachweis. Mehrspaltig, weil sechzig
   Zeilen untereinander eine Bildschirmlänge fressen, ohne mehr zu sagen. */
.credits-list {
    columns: 3 14rem;
    margin: .75rem 0 0;
    padding-left: 1.1rem;
    font-size: .9rem;
    line-height: 1.7;
}

/* ---------- Einladungen ---------- */

/* Der Kasten für Seiten ohne Anmeldung: Einladung annehmen, Hinweis auf einen
   ungültigen Link. Wie die Anmeldeseite aufgebaut, damit beides zusammengehört. */
.auth-card {
    max-width: 32rem;
    margin: 2rem auto;
    padding: 1.75rem;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-2);
}

.auth-card__head {
    display: flex;
    align-items: flex-start;
    gap: .9rem;
    margin-bottom: 1.25rem;
}

.auth-card__head .page__title { margin: 0 0 .25rem; }

/* Das Feld mit dem Einladungslink. Nichtproportionale Schrift, damit sich ein
   Kennwort aus 64 Zeichen überhaupt lesen lässt, und beim Klick alles markiert. */
.link-field {
    width: 100%;
    font-family: var(--font-mono);
    font-size: .8rem;
}

.card--link { border-color: var(--c-accent); }

.check-list { list-style: none; margin: .25rem 0 0; padding: 0; }
.check-list li { padding: .15rem 0; }
.check-list label { display: flex; align-items: center; gap: .5rem; }

/* Eine waagerechte Trennung innerhalb eines Formulars. */
.rule {
    margin: 1.25rem 0;
    border: 0;
    border-top: 1px solid var(--c-border);
}

/* Die Vorschlagsliste nach einem @ steht hier und nicht in task.css: Sie
   erscheint im Kartendialog wie im Chat, und die Chatseite laedt task.css
   gar nicht. Dort blieb die Liste deshalb unpositioniert im Fluss stehen
   und schob das Eingabefeld auseinander. */
/* ---------- Vorschläge nach dem @ ---------- */

/* Die Liste hängt am umgebenden Block und nicht am Dokument: So wandert sie
   mit, wenn der Dialog scrollt. */
.mention-list {
    position: absolute;
    z-index: 20;
    left: 0;
    right: 0;
    max-height: 12rem;
    margin: .2rem 0 0;
    padding: .25rem;
    overflow-y: auto;
    list-style: none;
    background: var(--c-surface);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow-2);
}

.mention-list[hidden] { display: none; }

/* Nach oben aufgeklappt — im Chat steht das Eingabefeld unten am Fenster, und
   eine Liste darunter läge außerhalb des Bildes. Welche Richtung gilt, misst
   der Controller am verfügbaren Platz. */
.mention-list--oben {
    top: auto;
    bottom: 100%;
    margin: 0 0 .2rem;
}

.mention-list__item {
    padding: .35rem .5rem;
    font-size: .9rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.mention-list__item span { color: var(--c-text-muted); }
.mention-list__item.is-active { background: var(--c-accent-soft); }


/* ---------- Schriftauswahl ---------- */

/* Jede Wahl steht in ihrer eigenen Schrift: Fünf Namen in derselben Schrift
   sagen nichts darüber, wie das Ergebnis aussieht. */
.font-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: .5rem;
    margin-top: .25rem;
}

.font-option {
    display: block;
    padding: .7rem .85rem;
    background: var(--c-surface);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--radius);
    cursor: pointer;
    transition: border-color var(--t), box-shadow var(--t);
}

.font-option:hover { border-color: var(--c-accent); }

.font-option:has(input:checked) {
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-ring);
}

.font-option input { margin-right: .4rem; }
.font-option__name { font-weight: 600; }

.font-option__probe {
    display: block;
    margin: .35rem 0 .3rem;
    font-size: 1.05rem;
    font-variant-numeric: tabular-nums;
}

.font-option__hint {
    display: block;
    font-size: .8rem;
    line-height: 1.4;

    /* Der Hinweis erklärt die Schrift und soll deshalb nicht in ihr stehen —
       sonst liest man ihn mit, statt die Probe darüber anzusehen. */
    font-family: var(--font);
}

/* ---------- Labels ---------- */

/*
 * Die Grundform eines Labels. Sie stand in board.css und liegt jetzt hier:
 * Labels erscheinen auf Karten, im Kartendialog **und** in ihrer eigenen
 * Verwaltung — und die lädt board.css nicht. Dort waren sie deshalb gar nicht
 * formatiert.
 */
.label-chip {
    padding: .05rem .4rem;
    font-size: .68rem;
    font-weight: 600;
    line-height: 1.5;
    color: #fff;
    background: var(--label-color, var(--c-text-muted));
    border-radius: var(--radius-pill);
}

.label-chip--dark-text { color: #1b1f24; }

/* ---------- Labelverwaltung ---------- */

.label-admin { margin: .75rem 0 0; padding: 0; list-style: none; }

.label-admin__row {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    padding: .5rem 0;
    border-top: 1px solid var(--c-border);
}

.label-admin__form { display: flex; align-items: center; gap: .5rem; flex: 1; }
.label-admin__name { flex: 1; min-width: 8rem; }

/*
 * Die Vorschau **ist** das Farbfeld.
 *
 * Das `input[type=color]` liegt unsichtbar über dem Chip und deckt ihn ganz
 * ab: Ein Klick irgendwo auf die Fläche öffnet die Farbauswahl des
 * Betriebssystems. Sichtbar bleibt der Name — so, wie das Label später auf der
 * Karte aussieht.
 *
 * Die Höhe kommt aus --control-h, damit Chip, Textfeld und Schaltfläche in
 * einer Zeile auf einer Linie stehen.
 */
.label-chip--edit {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 7rem;
    min-height: var(--control-h);
    padding: .1rem .75rem;
    font-size: .8rem;
    text-align: center;
    border-radius: var(--radius);
    box-shadow: inset 0 0 0 1px rgb(16 24 40 / .12);
    cursor: pointer;
}

.label-chip--edit .is-leer { opacity: .55; font-style: italic; }

/* Der Chip waechst mit dem Namen — und ein Name darf sechzig Zeichen lang
   sein. Damit er auf einem Telefon nicht die Zeile sprengt, endet er
   spaetestens an deren Rand und kuerzt dann mit Auslassungspunkten. Das
   vollstaendige Wort steht ohnehin im Feld daneben. */
.label-chip--edit { max-width: 100%; }

.label-chip--edit > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.label-chip__color {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    opacity: 0;
    cursor: pointer;
}

/* Der Fokusrahmen gehört sichtbar an den Chip, nicht an das unsichtbare Feld
   darüber — sonst ist beim Bedienen mit der Tastatur nicht zu sehen, wo man
   gerade steht. */
.label-chip--edit:focus-within {
    outline: none;
    box-shadow: inset 0 0 0 1px rgb(16 24 40 / .12), 0 0 0 3px var(--c-ring);
}

/* ---------- Reiter mit Inhaltsfläche ---------- */

/*
 * Laschen, die mit dem Bereich darunter verschmelzen.
 *
 * Die schlichte Variante `.tabs` (eine Zeile über einer Linie) gibt es
 * weiterhin für den Systembereich — dort führt jeder Reiter auf eine eigene
 * Seite, und es gibt keine Fläche, mit der etwas verschmelzen könnte. Hier
 * dagegen liegt der Inhalt unmittelbar darunter, und die Laschen sahen aus,
 * als gehörten sie nicht dazu.
 *
 * Der Kniff ist alt und einfach: Der aktive Reiter bekommt denselben Grund wie
 * die Fläche und wird um einen Pixel nach unten geschoben, sodass seine untere
 * Kante die obere Kante der Fläche verdeckt.
 */
.tabbed__tabs {
    display: flex;
    gap: .25rem;
    padding-left: .75rem;
    overflow-x: auto;
    scrollbar-width: none;
}

.tabbed__tabs::-webkit-scrollbar { display: none; }

.tabbed__tab {
    position: relative;
    z-index: 1;
    margin-bottom: -1px;
    padding: .5rem 1rem;
    font-family: inherit;
    font-size: .925rem;
    color: var(--c-text-muted);
    white-space: nowrap;
    background: var(--c-surface-alt);
    border: 1px solid var(--c-border);
    border-radius: var(--radius) var(--radius) 0 0;
    cursor: pointer;
    transition: color var(--t), background var(--t);
}

.tabbed__tab:hover { color: var(--c-text); background: var(--c-surface); }

.tabbed__tab[aria-selected="true"] {
    font-weight: 600;
    color: var(--c-accent);
    background: var(--c-surface);

    /* Die untere Kante fällt weg — genau das lässt Lasche und Fläche zu einem
       Stück werden. */
    border-bottom-color: var(--c-surface);
}

.tabbed__tab:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--c-ring);
}

.tabbed__body {
    padding: 1.25rem;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-1);
}

/*
 * Der Inhalt fährt beim Wechsel von links ein.
 *
 * Kurz und einmalig: Eine Bewegung, die man bewusst wahrnimmt, ist bei einem
 * Reiterwechsel zu viel — sie soll nur zeigen, dass sich etwas ausgetauscht
 * hat.
 */
@keyframes tabbed-einfahren {
    from { opacity: 0; transform: translateX(-10px); }
    to   { opacity: 1; transform: translateX(0); }
}

.tabbed__panel.is-eingefahren {
    animation: tabbed-einfahren 180ms cubic-bezier(.2, .8, .3, 1) both;
}

@media (prefers-reduced-motion: reduce) {
    .tabbed__panel.is-eingefahren { animation: none; }
}

/* Ohne JavaScript stehen alle Bereiche untereinander; dann braucht es eine
   Trennung zwischen ihnen. */
.tabbed__panel + .tabbed__panel { margin-top: 1.25rem; }
.tabbed__panel[hidden] + .tabbed__panel { margin-top: 0; }

/* ---------- Startseite: Zahlen, Verlauf ---------- */

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .75rem;
    margin: 0 0 1.25rem;
    padding: 0;
    list-style: none;
}

.stats__item {
    padding: .9rem 1rem;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-1);
}

/* Die Kacheln führen in die Agenda; der Verweis füllt die ganze Fläche, damit
   nicht nur die Zahl selbst anklickbar ist. */
.stats__item a {
    display: block;
    color: inherit;
    text-decoration: none;
}

.stats__value {
    display: block;
    font-size: 1.9rem;
    font-weight: 650;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.stats__label {
    display: block;
    margin-top: .15rem;
    font-size: .82rem;
    color: var(--c-text-muted);
}

/* Überfällig ist die einzige Zahl mit Farbe: die einzige, bei der Handeln
   nötig ist. Steht sie auf null, bleibt die Kachel unauffällig wie die
   anderen — eine rote Null wäre ein Fehlalarm. */
.stats__item--warn {
    background: var(--c-danger-soft);
    border-color: var(--c-danger);
}

.stats__item--warn .stats__value { color: var(--c-danger); }

/*
 * Zwei Spalten, solange Platz ist: links die eigenen Aufgaben, rechts der
 * Verlauf. Auf schmalen Fenstern untereinander, und dann zuerst die Aufgaben —
 * die Reihenfolge im Dokument stimmt bereits.
 */
.dashboard {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
    gap: var(--gap);
    align-items: start;
}

/* ---------- Verlauf ---------- */

.feed {
    margin: 0;
    padding: 0;
    list-style: none;
}

.feed__item {
    display: flex;
    gap: .75rem;
    padding: .55rem 0;
    font-size: .875rem;
    border-bottom: 1px solid var(--c-border);
}

.feed__item:last-child { border-bottom: 0; }
.feed__item:first-child { padding-top: 0; }

/* Feste Breite für den Zeitpunkt: So stehen die Uhrzeiten untereinander, und
   die Liste liest sich als Zeitleiste statt als Absatzfolge. */
.feed__time {
    flex: 0 0 8.5rem;
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
}

.feed__body { min-width: 0; }

.feed__project {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    margin-right: .35rem;
    font-size: .8rem;
    font-weight: 600;
    color: var(--c-text-muted);
    text-decoration: none;
}

.feed__project:hover { color: var(--c-text); }

.feed__text { margin-right: .3rem; }

.feed__task {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
    font-weight: 600;
}

@media (max-width: 40rem) {
    /* Auf dem Telefon steht der Zeitpunkt über dem Text statt daneben —
       8,5 rem für die Uhrzeit ließen sonst kaum Platz für den Satz. */
    .feed__item { flex-direction: column; gap: .1rem; }
    .feed__time { flex: none; }
}

/* Der Hinweis am Menüpunkt „Chat".
   Ein Punkt ohne Zahl: In einem Menü aus Wörtern wäre eine Ziffer ein
   Fremdkörper, und „da ist etwas" ist die ganze Aussage. Wie viel es ist,
   steht im Chat selbst. */
.nav-chat { position: relative; }

.nav-chat__dot {
    position: absolute;
    top: .25rem;
    right: .15rem;
    width: .45rem;
    height: .45rem;
    background: var(--c-danger);
    border-radius: 50%;
}
