/* Eigene Ergaenzungen zu Bootstrap. Praefix nlf- fuer alles Projekteigene. */

.nlf-app {
    font-size: 0.95rem;
}

/* Der Punkt sass 1,5 px unter der Textmitte - gemessen, nicht geschaetzt.
   Schuld war `vertical-align: middle`: es richtet an der Mitte der x-Hoehe
   aus, nicht an der Mitte der Zeile, und bei einer Versalie daneben faellt
   der Unterschied auf. Die Marke ist jetzt eine Flexbox; damit zentriert
   sich der Punkt an der wirklichen Mitte, unabhaengig von der Schrift. */
.navbar-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

/*
 * Der Markenpunkt sitzt auf der VERSALHOEHE, nicht auf der Zeilenmitte.
 *
 * Bis zum 27.8.2026 stand hier nichts zur senkrechten Lage - der Punkt hing
 * damit als `inline-block` mit seiner Unterkante auf der Grundlinie, seine
 * Mitte also 0,3rem darueber. Gemessen war alles in Ordnung: Kastenmitte
 * des Punktes gegen Kastenmitte der Marke ergab 0,0 px, und der Pruefstand
 * meldete gruen.
 *
 * Der Kasten der Zeile ist aber nicht das, was man sieht. Er reicht bis
 * unter die Grundlinie, weil dort Unterlaengen Platz haben - und
 * "StreamMaster" hat keine einzige. Die Buchstaben stehen deshalb sichtbar
 * hoeher als ihr Kasten, und der Punkt sass 2,4 px zu tief.
 *
 * Gemessen statt gerechnet, und die erste Rechnung war falsch: sie ging von
 * der Versalhoehe aus (0,72em) und ergab 0,12em Versatz. "StreamMaster" hat
 * aber Oberlaengen - l, t, d reichen hoeher als das M -, und die Farbe auf
 * dem Schirm reicht damit weiter nach oben als jede Versalrechnung. Mit
 * 0,12em stand der Punkt 1,4 px zu HOCH, vorher 1,0 px zu tief.
 *
 * Der Zielwert ist die Mitte dessen, was man sieht: von der Oberkante der
 * hoechsten Buchstaben bis zur Grundlinie - "StreamMaster" hat keine
 * Unterlaenge. Der Browser misst das selbst
 * (`TextMetrics.actualBoundingBoxAscent`), und `bin/qa/align.mjs` prueft
 * seitdem GEGEN DIESE KANTE statt gegen den Zeilenkasten.
 */
.nlf-brand-dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: var(--bs-primary);
    flex-shrink: 0;
    display: inline-block;
    vertical-align: baseline;
    position: relative;
    bottom: 0.05em;
}

/* Katalog als Rasteransicht: feste Spaltenbreite, damit die Poster ein
   ruhiges Bild ergeben, auch wenn ihre Seitenverhaeltnisse schwanken. */
.nlf-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    gap: 0.9rem;
}

.nlf-card {
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.nlf-card__poster {
    aspect-ratio: 2 / 3;
    width: 100%;
    object-fit: cover;
    background: var(--bs-tertiary-bg);
    display: block;
}

.nlf-card__body {
    padding: 0.5rem 0.6rem 0.6rem;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.nlf-card__title {
    font-size: 0.82rem;
    line-height: 1.25;
    font-weight: 600;
    /* Zwei Zeilen, dann abschneiden - sonst springt das Raster. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.nlf-card__meta {
    font-size: 0.72rem;
    color: var(--bs-secondary-color);
}

/* Listenansicht: dieselbe Datenquelle, andere Darstellung. */
.nlf-grid--list {
    display: block;
}

.nlf-grid--list .nlf-card {
    flex-direction: row;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.35rem;
}

.nlf-grid--list .nlf-card__poster {
    width: 2.6rem;
    aspect-ratio: 2 / 3;
    flex-shrink: 0;
}

.nlf-grid--list .nlf-card__title {
    -webkit-line-clamp: 1;
}

.nlf-grid--list .nlf-card__body {
    flex-direction: row;
    align-items: center;
    gap: 1rem;
    width: 100%;
}

.nlf-grid--list .nlf-card__title {
    flex: 1 1 auto;
}

#nlf-job-log {
    background: var(--bs-tertiary-bg);
    white-space: pre-wrap;
    word-break: break-word;
}

/* Karten sind im Frontend anklickbar - Linkfarbe darf nicht durchschlagen. */
a.nlf-card {
    text-decoration: none;
    color: inherit;
}

a.nlf-card:hover {
    border-color: var(--bs-primary);
}

/* Trefferquote sitzt auf dem Poster. */
.nlf-card__posterwrap {
    position: relative;
}

.nlf-card__score {
    position: absolute;
    top: 0.35rem;
    right: 0.35rem;
    font-size: 0.68rem;
    opacity: 0.92;
}

.nlf-grid--list .nlf-card__posterwrap {
    flex-shrink: 0;
}

/*
 * Listenansicht auf dem Telefon. M. Martin am 13.09.2026: "Titel sollte komplett
 * angezeigt werden. Darunter die Metadaten." Bei 400 px standen Titel, Jahr und
 * Verfahren nebeneinander, und der Titel endete nach wenigen Zeichen mit "...".
 * Unter 768 px steht der Titel ganz, Jahr und Groesse darunter, die Verfahren
 * in der dritten Zeile. Das Bild bleibt links oben.
 */
@media (max-width: 767.98px) {
    .nlf-grid--list .nlf-card {
        align-items: flex-start;
    }
    .nlf-grid--list .nlf-card__body {
        flex-direction: column;
        align-items: stretch;
        gap: 0.15rem;
        min-width: 0;
    }
    .nlf-grid--list .nlf-card__title {
        display: block;
        -webkit-line-clamp: unset;
        overflow: visible;
        overflow-wrap: anywhere;
    }
}

/*
 * Fassungen und Folgen auf der Titelseite (13.09.2026): jede Zeile eine
 * Schaltflaeche ueber die volle Breite, der Name ganz, die Angaben darunter.
 */
.nlf-episode {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    text-align: left;
    font-size: .875rem;
}
.nlf-episode__play {
    flex: 0 0 1rem;
    color: var(--bs-primary);
}
.nlf-episode.active .nlf-episode__play,
.nlf-episode.active .nlf-episode__meta,
.nlf-episode.active .nlf-episode__no {
    color: inherit;
}
.nlf-episode__no {
    flex: 0 0 auto;
    min-width: 2.6rem;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: var(--bs-secondary-color);
}
.nlf-episode__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}
.nlf-episode__title {
    overflow-wrap: anywhere;
}
.nlf-episode__title.font-monospace {
    font-size: .8rem;
}
.nlf-episode__tags:empty {
    display: none;
}
.nlf-episode__meta {
    font-size: .78rem;
    color: var(--bs-secondary-color);
}
.nlf-episode--off {
    color: var(--bs-secondary-color);
}
/*
 * Vorschaubild je Fassung und Folge (14.09.2026): eine Kachel des Vorschaustreifens,
 * 160x90 geliefert, hier in 16:9 verkleinert. Der schwarze Grund fuellt, solange sie laedt.
 *
 * Das Abspielsymbol liegt auf dem Bild (M. Martin, 14.09.2026: „Bitte den Play-Button auf das
 * Cover. Spart Platz.“). Ohne Kachel bleibt der Kasten leer und traegt das Symbol trotzdem;
 * so stehen Nummer und Name aller Zeilen untereinander.
 */
.nlf-episode__cover {
    position: relative;
    flex: 0 0 auto;
    align-self: center;
    width: 112px;
    height: 63px;
    border-radius: .25rem;
    background: #000;
    overflow: hidden;
}
.nlf-episode--off .nlf-episode__cover {
    background: var(--bs-tertiary-bg);
}
.nlf-episode__thumb {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.nlf-episode__cover .nlf-play {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: calc(var(--nlf-play-size) / -2) 0 0 calc(var(--nlf-play-size) / -2);
}
/* Die aeltere Regel fuer .active faerbt das Symbol in der Zeilenfarbe; auf dem hellen Kreis waere es weg. */
.nlf-episode.active .nlf-play {
    color: var(--bs-dark);
}
/*
 * Auf dem Telefon kein Vorschaubild: mit 80 px daneben wurde eine Zeile bei 390 px bis zu
 * 160 px hoch (titlepage.mjs erlaubt 120), der Name brach nach wenigen Zeichen um. Der Kasten
 * schrumpft dort auf den Kreis und rueckt vor die Nummer.
 */
@media (max-width: 575.98px) {
    .nlf-episode__cover {
        order: -1;
        flex: 0 0 1.5rem;
        width: 1.5rem;
        height: 1.5rem;
        background: none;
        overflow: visible;
    }
    .nlf-episode--off .nlf-episode__cover {
        background: none;
    }
    .nlf-episode__thumb {
        display: none;
    }
    .nlf-episode__cover .nlf-play {
        --nlf-play-size: 1.5rem;
    }
}

/*
 * Ein Abspielsymbol fuer alle Listen (14.09.2026). M. Martin: "Play-Button, also Controls, sollen
 * ueberall gleich aussehen. Also unterhalb Videos, Staffeln, etc. das vom Player nehmen."
 * Vorbild ist der Startknopf ueber dem Plakat (player.css, .nlf-pl-go): heller Kreis, dunkles
 * Dreieck aus demselben Pfad wie im Abspieler, beim Ueberfahren 8 % groesser. Eine Maske
 * zeichnet das Dreieck, das Element bleibt leer: <span class="nlf-play" aria-hidden="true"></span>.
 * --bare zeigt nur das Dreieck in der Schriftfarbe, fuer Marken auf Bildern.
 */
.nlf-play {
    --nlf-play-size: 2rem;
    position: relative;
    display: inline-block;
    flex: 0 0 auto;
    width: var(--nlf-play-size);
    height: var(--nlf-play-size);
    border-radius: 50%;
    background: var(--bs-light);
    color: var(--bs-dark);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
    vertical-align: middle;
    transition: transform .12s ease-out;
}
.nlf-play::before {
    content: "";
    position: absolute;
    inset: 0 0 0 6%;   /* wie padding-left am Startknopf: das Dreieck wirkt sonst nach links versetzt */
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 2.5v11l9-5.5-9-5.5z'/%3E%3C/svg%3E") center / 42% no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 2.5v11l9-5.5-9-5.5z'/%3E%3C/svg%3E") center / 42% no-repeat;
}
.nlf-play--sm {
    --nlf-play-size: 1.5rem;
}
.nlf-play--bare {
    --nlf-play-size: 1em;
    background: none;
    box-shadow: none;
    color: inherit;
    vertical-align: -.125em;
    filter: drop-shadow(0 0 1px rgba(0, 0, 0, .8));
}
.nlf-play--bare::before {
    inset: 0;
    -webkit-mask-size: 100%;
    mask-size: 100%;
}
.nlf-pl-pick:hover .nlf-play,
.nlf-pl-pick:focus-visible .nlf-play,
.nlf-audio-track:not([disabled]):hover .nlf-play,
.nlf-audio-track:focus-visible .nlf-play {
    transform: scale(1.08);
}
.nlf-audio-track .nlf-play {
    align-self: center;
}
/* ── Bereich Foto/Video (14.09.2026) ────────────────────────────────────────────
 *
 * Links die Monate, rechts das Raster. Unter 768 px stehen die Monate als waagerechte Leiste
 * ueber dem Raster. Die Grossansicht liegt fest ueber allem, das Bild passt sich ein.
 */
.nlf-photo-layout {
    display: grid;
    grid-template-columns: 11rem minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
}
.nlf-photo-main {
    min-width: 0;
}
.nlf-photo-months {
    position: sticky;
    top: 1rem;
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
}
/* Ein Jahr ist eine Zeile mit Dreieck; aufgeklappt ist nur das Jahr des gewaehlten Monats. */
.nlf-photo-months__year {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    width: 100%;
    margin-top: .35rem;
    padding: .2rem .5rem;
    border: 0;
    border-radius: .25rem;
    background: transparent;
    color: var(--bs-secondary-color);
    font-size: .8rem;
    font-weight: 600;
    text-align: left;
}
.nlf-photo-months__year > span:first-child::before {
    content: '▸ ';
}
.nlf-photo-months__year[aria-expanded="true"] > span:first-child::before {
    content: '▾ ';
}
.nlf-photo-months__year:hover {
    background: var(--bs-secondary-bg);
}
.nlf-photo-months__item {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    width: 100%;
    padding: .2rem .5rem;
    border: 0;
    border-radius: .25rem;
    background: transparent;
    color: inherit;
    font-size: .875rem;
    text-align: left;
}
.nlf-photo-months__item:hover,
.nlf-photo-months__item.active {
    background: var(--bs-secondary-bg);
}
.nlf-photo-months__item.active {
    font-weight: 600;
}
.nlf-photo-months__count {
    color: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
}
@media (max-width: 767.98px) {
    .nlf-photo-layout {
        grid-template-columns: minmax(0, 1fr);
        gap: .75rem;
    }
    .nlf-photo-months {
        position: static;
        display: flex;
        align-items: center;
        gap: .25rem;
        max-height: none;
        overflow-x: auto;
        overflow-y: hidden;
        white-space: nowrap;
    }
    .nlf-photo-months__group,
    .nlf-photo-months__list {
        display: flex;
        align-items: center;
        gap: .25rem;
    }
    .nlf-photo-months__year,
    .nlf-photo-months__item {
        width: auto;
        margin: 0;
        white-space: nowrap;
    }
}
.nlf-photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .4rem;
}
@media (max-width: 575.98px) {
    .nlf-photo-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
.nlf-photo {
    position: relative;
    aspect-ratio: 1;
    padding: 0;
    border: 0;
    border-radius: .25rem;
    overflow: hidden;
    background: #000;
}
.nlf-photo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.nlf-photo__clip {
    position: absolute;
    left: .3rem;
    bottom: .3rem;
    padding: 0 .35rem;
    border-radius: .2rem;
    background: rgba(0, 0, 0, .65);
    color: #fff;
    font-size: .72rem;
}
.nlf-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    background: rgba(0, 0, 0, .92);
}
/* Bild links, Karte rechts; unter 768 px die Karte unter dem Bild (14.09.2026). */
.nlf-lightbox__body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
}
.nlf-lightbox__stage {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .5rem;
}
.nlf-lightbox__map {
    position: relative;
    flex: 0 0 40%;
    min-width: 0;
    background: #1f2326;
}
.nlf-lightbox__maptarget {
    position: absolute;
    inset: 0;
}
.nlf-lightbox__mapnote {
    position: absolute;
    top: .75rem;
    left: .75rem;
    right: .75rem;
    padding: .4rem .6rem;
    border-radius: .25rem;
    background: rgba(0, 0, 0, .7);
    color: #fff;
    font-size: .85rem;
}
.nlf-lightbox__maplink {
    position: absolute;
    right: .5rem;
    bottom: 1.8rem;
    padding: .1rem .45rem;
    border-radius: .2rem;
    background: rgba(0, 0, 0, .65);
    color: #fff;
    font-size: .8rem;
}
.nlf-lightbox__maptoggle {
    padding: 0;
    border: 0;
    background: transparent;
    color: #fff;
    text-decoration: underline;
}
@media (max-width: 767.98px) {
    .nlf-lightbox__body {
        flex-direction: column;
    }
    .nlf-lightbox__map {
        flex: 0 0 42vh;
    }
}
.nlf-lightbox__stage img,
.nlf-lightbox__stage video {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}
/* Clips im Abspieler der Filme (14.09.2026): so breit wie der Platz, nie hoeher als der Bildschirm. */
.nlf-lightbox__stage .nlf-player {
    width: min(100%, calc((100vh - 10rem) * 16 / 9));
    box-shadow: none;
}
.nlf-lightbox__stage .nlf-player .video-js {
    max-height: calc(100vh - 10rem);
}
/*
 * Telefon: die Angaben unter dem Bild ueber die ganze Breite, die Knoepfe darunter in einer Zeile.
 * Vorher teilten sich Angaben und vier Knoepfe 390 px, und jeder Tag stand in einer eigenen Zeile.
 */
@media (max-width: 575.98px) {
    .nlf-lightbox__bar {
        flex-wrap: wrap;
        padding: .5rem .75rem;
    }
    .nlf-lightbox__info {
        flex-basis: 100%;
        order: -1;
    }
    #nlf-lightbox-next {
        margin-right: auto;
    }
}
.nlf-lightbox__note {
    position: absolute;
    left: 50%;
    bottom: 1rem;
    transform: translateX(-50%);
    padding: .4rem .8rem;
    border-radius: .25rem;
    background: rgba(0, 0, 0, .75);
    color: #fff;
    font-size: .85rem;
}
.nlf-lightbox__bar {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem 1rem;
    color: #fff;
    font-size: .85rem;
}
.nlf-lightbox__info {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}
.nlf-lightbox__path {
    color: rgba(255, 255, 255, .6);
    font-size: .78rem;
}

/*
 * Tags (14.09.2026, Punkt 26): Suchfeld mit Vorschlaegen ueber dem Raster, Tags in der
 * Grossansicht, Auswahl mehrerer Fotos. Von Hand gesetzte Tags tragen einen durchgezogenen Rand,
 * automatische einen gestrichelten.
 */
.nlf-tag-search {
    position: relative;
}
.nlf-tag-field {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .3rem;
    padding: .25rem .4rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background: var(--bs-body-bg);
}
.nlf-tag-field:focus-within {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 .2rem rgba(var(--bs-primary-rgb), .25);
}
.nlf-tag-field__chips {
    display: contents;
}
.nlf-tag-field__input {
    flex: 1 1 10rem;
    min-width: 0;
    padding: .2rem;
    border: 0;
    outline: 0;
    background: transparent;
    color: inherit;
    font-size: .9rem;
}
.nlf-tag-menu {
    position: absolute;
    z-index: 1070;
    top: 100%;
    left: 0;
    min-width: 14rem;
    max-width: min(24rem, 100vw - 2rem);
    max-height: 18rem;
    margin-top: .2rem;
    padding: .25rem 0;
    overflow-y: auto;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background: var(--bs-body-bg);
    box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .3);
}
.nlf-tag-menu--up {
    top: auto;
    bottom: 100%;
    margin: 0 0 .2rem;
}
.nlf-tag-menu__item {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    padding: .3rem .75rem;
    border: 0;
    background: none;
    color: var(--bs-body-color);
    font-size: .875rem;
    text-align: left;
}
.nlf-tag-menu__item.active,
.nlf-tag-menu__item:hover {
    background: var(--bs-tertiary-bg);
}
.nlf-tag-menu__count {
    color: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
}
.nlf-tag {
    display: inline-flex;
    align-items: center;
    max-width: 100%;
    border: 1px dashed var(--bs-secondary-color);
    border-radius: 1rem;
    font-size: .78rem;
    line-height: 1.6;
}
.nlf-tag--hand {
    border-style: solid;
}
.nlf-tag--search {
    border: 1px solid var(--bs-primary);
    background: var(--bs-primary);
    color: #fff;
}
.nlf-tag__name {
    overflow: hidden;
    padding: 0 .55rem;
    border: 0;
    background: none;
    color: inherit;
    font-size: inherit;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.nlf-tag__remove {
    padding: 0 .5rem 0 0;
    border: 0;
    background: none;
    color: inherit;
    font-size: .95rem;
    line-height: 1;
    opacity: .75;
}
.nlf-tag__remove:hover,
.nlf-tag__remove:focus-visible {
    opacity: 1;
}
.nlf-lightbox__tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .3rem;
    margin-top: .35rem;
}
.nlf-lightbox__tags .nlf-tag {
    border-color: rgba(255, 255, 255, .55);
    color: #fff;
}
.nlf-lightbox__tagadd {
    display: inline-block;
}
/* Text im Bild (Stufe 5): zugeklappt, aufgeklappt hoechstens acht Zeilen hoch und rollbar. */
.nlf-lightbox__text {
    margin-top: .3rem;
    font-size: .78rem;
}
.nlf-lightbox__text summary {
    color: rgba(255, 255, 255, .75);
    cursor: pointer;
}
.nlf-lightbox__text div {
    max-height: 8rem;
    overflow-y: auto;
    white-space: pre-line;
    color: rgba(255, 255, 255, .85);
}
.nlf-tag-add {
    width: 8rem;
    padding: 0 .55rem;
    border: 1px dashed rgba(255, 255, 255, .55);
    border-radius: 1rem;
    background: transparent;
    color: #fff;
    font-size: .78rem;
    line-height: 1.6;
}
.nlf-tag-add::placeholder {
    color: rgba(255, 255, 255, .7);
}
.nlf-tag-add:focus {
    border-style: solid;
    outline: 0;
}
.nlf-select-bar {
    position: sticky;
    top: 0;
    z-index: 1020;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin-bottom: .75rem;
    padding: .5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background: var(--bs-tertiary-bg);
}
.nlf-select-bar__field {
    flex: 1 1 12rem;
}
.nlf-photo.is-selected {
    outline: 3px solid var(--bs-primary);
    outline-offset: -3px;
}
.nlf-photo.is-selected::after {
    content: "✓";
    position: absolute;
    top: .3rem;
    right: .3rem;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: var(--bs-primary);
    color: #fff;
    font-size: .85rem;
    line-height: 1.4rem;
    text-align: center;
}
/* Seite Gesichter (14.09.2026): je Gruppe eine Karte mit Ausschnitten, Namensfeld und zwei Knoepfen. */
.nlf-faces {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
    gap: .75rem;
}
.nlf-faces__crops {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
}
.nlf-faces__crops img {
    display: block;
    width: 64px;
    height: 64px;
    border-radius: .25rem;
    object-fit: cover;
    background: #000;
}
.nlf-faces__name {
    flex: 1 1 8rem;
    min-width: 0;
}
.nlf-faces-people {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
}
.nlf-faces-people a {
    text-decoration: none;
}
.nlf-photo-notice {
    position: fixed;
    z-index: 1090;
    left: 50%;
    bottom: 1rem;
    max-width: calc(100% - 2rem);
    padding: .5rem .9rem;
    border-radius: .4rem;
    background: rgba(0, 0, 0, .85);
    color: #fff;
    font-size: .875rem;
    transform: translateX(-50%);
}

/* ── Bereich Audio (14.09.2026) ─────────────────────────────────────────────────
 *
 * Buchstaben oben, Interpreten links, Alben oder Stücke rechts, die Abspielleiste fest unten.
 * Unter 768 px steht die Interpretenliste als begrenzte Liste über den Alben.
 */
.nlf-audio-letters {
    display: flex;
    flex-wrap: wrap;
    gap: .2rem;
    margin-bottom: .75rem;
}
.nlf-audio-letters button {
    min-width: 2rem;
    padding: .15rem .4rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .25rem;
    background: transparent;
    color: inherit;
    font-size: .85rem;
}
.nlf-audio-letters button.active {
    border-color: var(--bs-primary);
    background: var(--bs-primary);
    color: #fff;
}
.nlf-audio-layout {
    display: grid;
    grid-template-columns: 16rem minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
    padding-bottom: 5rem;
}
.nlf-audio-artists {
    position: sticky;
    top: 1rem;
    max-height: calc(100vh - 14rem);
    overflow-y: auto;
}
.nlf-audio-artists button {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    width: 100%;
    padding: .2rem .5rem;
    border: 0;
    border-radius: .25rem;
    background: transparent;
    color: inherit;
    font-size: .875rem;
    text-align: left;
}
.nlf-audio-artists button:hover,
.nlf-audio-artists button.active {
    background: var(--bs-secondary-bg);
}
.nlf-audio-artists small {
    color: var(--bs-secondary-color);
    white-space: nowrap;
}
.nlf-audio-main {
    min-width: 0;
}
.nlf-audio-albums {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .75rem;
}
/*
 * Spalte mit Inhalt oben (14.09.2026). Das Raster streckt alle Karten einer Zeile auf dieselbe Hoehe,
 * und ein Button zentriert seinen Inhalt senkrecht: neben "Godfathers Of Techno (CD2)" mit zwei
 * Zeilen stand das Cover von "Hardbass Chapter Five" 10 px tiefer.
 */
.nlf-audio-album {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    text-align: left;
}
.nlf-audio-album img,
.nlf-audio-album__blank {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: .375rem;
    background: var(--bs-secondary-bg);
}
.nlf-audio-album__name {
    display: block;
    margin-top: .3rem;
    font-size: .875rem;
    overflow-wrap: anywhere;
}
.nlf-audio-album__meta {
    display: block;
    color: var(--bs-secondary-color);
    font-size: .78rem;
}
.nlf-audio-track {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    font-size: .875rem;
    text-align: left;
}
.nlf-audio-track__no {
    flex: 0 0 2.2rem;
    color: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
}
.nlf-audio-track__title {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}
.nlf-audio-track__time {
    flex: 0 0 auto;
    color: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
}
.nlf-audio-player {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .5rem 1rem;
    border-top: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
}
.nlf-audio-player__now {
    flex: 0 1 30%;
    min-width: 0;
    overflow: hidden;
    font-size: .85rem;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.nlf-audio-player audio {
    flex: 1 1 auto;
    min-width: 0;
}
@media (max-width: 767.98px) {
    .nlf-audio-layout {
        grid-template-columns: minmax(0, 1fr);
    }
    .nlf-audio-artists {
        position: static;
        max-height: 14rem;
    }
    .nlf-audio-player {
        flex-direction: column;
        align-items: stretch;
        gap: .25rem;
    }
    .nlf-audio-player__now {
        flex-basis: auto;
    }
}

/* ── Karte der Aufnahmeorte (14.09.2026) ─────────────────────────────────────── */
.nlf-map {
    position: relative;
    height: calc(100vh - 13rem);
    min-height: 22rem;
    border-radius: .375rem;
    overflow: hidden;
    background: #e9ecef;
}
.nlf-map-popup {
    min-width: 14rem;
    max-width: 20rem;
    padding: .5rem;
    border-radius: .375rem;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    box-shadow: 0 .25rem 1rem rgba(0, 0, 0, .45);
    font-size: .85rem;
}
.nlf-map-popup__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .4rem;
}
.nlf-map-popup__grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: .25rem;
}
.nlf-map-popup__grid a {
    position: relative;
    display: block;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: .2rem;
    background: #000;
}
.nlf-map-popup__grid img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.nlf-map-popup__grid span {
    position: absolute;
    left: .2rem;
    bottom: 0;
    color: #fff;
    font-size: .7rem;
    text-shadow: 0 0 2px #000;
}
.nlf-map-popup__more {
    margin-top: .35rem;
    color: var(--bs-secondary-color);
    font-size: .78rem;
}

/* Staffel-Cover im Kopf einer Staffel (14.09.2026), 2:3 wie ein Poster. */
.nlf-season__poster {
    width: 32px;
    height: 48px;
    object-fit: cover;
    border-radius: .2rem;
    margin-right: .5rem;
    vertical-align: middle;
    background: #000;
}

/* ── Mini-Sequenz beim Zeigen ────────────────────────────────────────────────
 *
 * Der Streifen der Zeitleiste, hier als Daumenkino: ein Sprite mit zehn mal
 * zehn Kacheln zu je 160x90. Das Bild ist zehnmal so breit und zehnmal so
 * hoch wie der Rahmen, damit EINE Kachel den Rahmen genau fuellt; ein
 * `translate` um Vielfache von 10 Prozent der Bildgroesse springt dann exakt
 * eine Kachel weiter. Mit `background-position` in Prozent ginge es nicht:
 * dort haengt der Schritt an der Ueberlaufhoehe und damit am Seitenverhaeltnis
 * der Kachel.
 *
 * Der Rahmen ist 16:9 und liegt mittig ueber dem hochkanten Poster. Der
 * schwarze Grund fuellt, was daneben frei bleibt.
 */
.nlf-card__peek {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #000;
    opacity: 0;
    transition: opacity .12s linear;
    pointer-events: none;
}

.nlf-card__peek--on {
    opacity: 1;
}

.nlf-card__peekframe {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    overflow: hidden;
}

.nlf-card__peekframe img {
    position: absolute;
    top: 0;
    left: 0;
    width: 1000%;
    height: 1000%;
    max-width: none;
    image-rendering: auto;
}

/*
 * Ein Finger hat keinen Zeiger. Ohne diese Schranke bliebe die Sequenz nach
 * einer Beruehrung stehen, bis man woanders hintippt, dieselbe Ueberlegung
 * wie beim Kontextmenue des Abspielers.
 */
@media (hover: none), (pointer: coarse) {
    .nlf-card__peek { display: none; }
}

/* Der Adminbereich hebt sich farblich ab, damit man ihn nicht verwechselt. */
.nlf-brand-dot--admin {
    background: var(--bs-warning);
}

/* Befunddetails als lesbare Liste statt als rohes JSON. */
.nlf-detail {
    list-style: none;
    padding-left: 0;
    margin-bottom: 0;
    font-size: 0.78rem;
    line-height: 1.35;
}

.nlf-detail .nlf-detail {
    padding-left: 0.9rem;
    border-left: 2px solid var(--bs-border-color);
    margin-top: 0.15rem;
}

.nlf-detail__key {
    color: var(--bs-secondary-color);
}

/* Tabellenzellen oben ausrichten - bei mehrzeiligen Detaillisten liest sich
   das deutlich ruhiger als vertikal zentriert. */
.table > :not(caption) > * > * {
    vertical-align: top;
}

/* Tabellen mit fester Spaltenaufteilung.
 *
 * Ohne `table-layout: fixed` verhandelt der Browser die Breiten nach Inhalt -
 * eine Spalte mit langen Pfaden zieht dann alle anderen zusammen. Mit fester
 * Aufteilung gelten die Prozentangaben aus den Kopfzellen. Die Mindestbreite
 * sorgt dafuer, dass auf schmalen Anzeigen gescrollt statt gequetscht wird;
 * dafuer ist die Tabelle in `.table-responsive` eingefasst. */
.nlf-table-fixed {
    table-layout: fixed;
    min-width: 64rem;
}

/* Lange Pfade und Releasenamen muessen umbrechen duerfen, sonst sprengen sie
   die zugewiesene Spaltenbreite trotzdem. */
.nlf-table-fixed td,
.nlf-table-fixed th {
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* Etiketten in schmalen Spalten muessen umbrechen duerfen.
 *
 * Bootstrap setzt Badges auf `white-space: nowrap`. In einer Spalte fester
 * Breite lief ein langes Etikett dadurch aus der Zelle heraus und legte sich
 * ueber die Nachbarspalte - der Pfad begann sichtbar mit "e/A/..." statt
 * "filme/A/...". */
.nlf-badge-wrap {
    white-space: normal;
    text-align: left;
    display: inline-block;
    max-width: 100%;
}

/* Befehlsvorschlaege zu einem Befund.
   Die Befehle sind lang und in der schmalen Detailspalte unlesbar. Sie
   bekommen deshalb eine eigene Zeile, die von Spalte 2 bis zum Rand reicht.
   Auf- und zugeklappt wird ueber ein verstecktes Kontrollkaestchen - so
   braucht die Tabelle kein JavaScript. */
.nlf-fixtoggle {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.nlf-fix__toggle {
    display: inline-block;
    margin-top: .35rem;
    cursor: pointer;
    font-size: .75rem;
    color: var(--bs-secondary-color);
}

.nlf-fix__toggle::before {
    content: "\25b8\00a0";
}

.nlf-fix__toggle:hover {
    color: var(--bs-body-color);
}

/* Der Pfeil schlaegt um, egal ob der Umschalter in einer Tabellenzeile oder
   in einer Karte sitzt. Frueher stand hier nur "tr:" - im Eingangskorb, der
   Karten benutzt, tat der Umschalter deshalb sichtbar gar nichts. */
:is(tr, .nlf-todo):has(.nlf-fixtoggle:checked) .nlf-fix__toggle::before {
    content: "\25be\00a0";
}

/* Standardmaessig zu. Die Zeile erscheint erst, wenn das Kaestchen der
   Zeile davor gesetzt ist. */
tr.nlf-fixrow {
    display: none;
}

tr:has(.nlf-fixtoggle:checked) + tr.nlf-fixrow {
    display: table-row;
}

tr.nlf-fixrow > td {
    padding-top: 0;
    border-top: 0;
}

.nlf-fix {
    border-left: 2px solid var(--bs-border-color);
    padding-left: .6rem;
    margin-bottom: .3rem;
}

.nlf-fix__note {
    font-size: .78rem;
    color: var(--bs-secondary-color);
    margin-bottom: .4rem;
}

.nlf-fix__label {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-secondary-color);
    margin-top: .4rem;
}

.nlf-fix__cmd {
    font-size: .74rem;
    line-height: 1.5;
    background: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    padding: .5rem .6rem;
    margin: .15rem 0 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    user-select: all;
}

.nlf-fix__cmd--real {
    border-left: 3px solid var(--bs-warning);
}

/* Sammelskript ueber mehrere Befunde.
   Die Leiste bleibt beim Blaettern durch lange Listen sichtbar - sonst muss
   man nach jedem Ankreuzen wieder nach oben scrollen, um zu erzeugen. */
.nlf-batch {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    padding: .5rem .6rem;
}

.nlf-batch__out {
    margin-top: .5rem;
    border-top: 1px solid var(--bs-border-color);
    padding-top: .5rem;
}

/* Die Vorschau darf die Seite nicht sprengen: das Skript kann tausend
   Zeilen haben. Gescrollt wird im Block, nicht im Dokument. */
.nlf-batch__script {
    max-height: 24rem;
    overflow: auto;
    white-space: pre;
    user-select: text;
}

.nlf-batch__list {
    font-size: .78rem;
    margin: .25rem 0;
}

.nlf-batch__list > summary {
    cursor: pointer;
}

.nlf-batch__item {
    padding-left: 1rem;
    overflow-wrap: anywhere;
}

/* Zeilen ohne ausfuehrbaren Befehl bekommen statt eines Kaestchens einen
   Punkt - so ist die Spalte ruhig und trotzdem erklaert sich die Luecke. */
.nlf-pick-none {
    color: var(--bs-secondary-color);
    opacity: .4;
}

/* Spurauflistung zu einem Befund. Steht ueber den Befehlen, weil sich der
   Befund ohne sie nicht beurteilen laesst - "Tonspur 2" sagt nichts,
   solange unklar ist, welche Spuren die Datei ueberhaupt hat. */
.nlf-streams-block {
    margin-bottom: .75rem;
}

.nlf-streams {
    font-size: .74rem;
    margin-top: .25rem;
}

.nlf-streams th {
    font-weight: 600;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}

.nlf-streams td {
    vertical-align: top;
}

/* Die vom Befund betroffene Spur heraushebe - sonst muss man sie in der
   Tabelle suchen. */
.nlf-streams__hit > td {
    background: color-mix(in srgb, var(--bs-warning) 14%, transparent);
}

.nlf-streams__mark {
    display: inline-block;
    margin-left: .3rem;
    padding: 0 .3rem;
    border-radius: var(--bs-border-radius-sm);
    background: var(--bs-warning);
    color: var(--bs-dark);
    font-size: .62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
    white-space: nowrap;
}

.nlf-streams__hint {
    font-size: .7rem;
    color: var(--bs-secondary-color);
    margin-top: .3rem;
    line-height: 1.5;
}

.nlf-streams__hint code {
    font-size: .68rem;
    color: var(--bs-body-color);
}

/* Beschriftung des Fortschrittsbalkens.
   Sie liegt UEBER dem ganzen Balken statt im gefuellten Teil: bei einem
   Prozent stand die Schrift sonst in einem wenige Pixel breiten Streifen,
   war abgeschnitten und wanderte beim Fortschreiten mit. */
.nlf-progress {
    position: relative;
}

.nlf-progress__label {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .78rem;
    font-weight: 600;
    line-height: 1;
    color: var(--bs-body-color);
    /* Lesbar sowohl ueber dem gefuellten als auch ueber dem leeren Teil. */
    text-shadow:
        0 0 3px var(--bs-body-bg),
        0 0 3px var(--bs-body-bg),
        0 0 5px var(--bs-body-bg);
    pointer-events: none;
    white-space: nowrap;
    overflow: hidden;
}

/* Spalte "Sprache" in der Befundliste.
   Ersetzt die frueher eigene Urteilsliste: je Tonspur steht dort, was in der
   Datei gekennzeichnet ist und was die Sprachpruefung gehoert hat. Kompakt,
   weil bis zu acht Spuren untereinander passen muessen. */
.nlf-lang__row {
    font-size: .76rem;
    line-height: 1.45;
}

.nlf-lang__track {
    display: inline-block;
    min-width: 1.6rem;
    color: var(--bs-secondary-color);
    font-family: var(--bs-font-monospace);
}

.nlf-lang__is {
    display: inline-block;
    min-width: 2.2rem;
    font-family: var(--bs-font-monospace);
}

/* Zusammenfassung der Sprachpruefung ueber der Liste - sagt, WIE WEIT sie
   ist. Ohne das liesse sich nicht unterscheiden, ob ein leeres Feld
   "geprueft und in Ordnung" oder "noch nicht drangewesen" heisst. */
.nlf-langsum {
    border-left: 3px solid var(--bs-info);
    padding: .25rem .6rem;
    background: var(--bs-tertiary-bg);
    border-radius: var(--bs-border-radius-sm);
}

/* "Ist ⇒ Soll" - was der Befehl aendert.
   Zwei Blasen statt Durchstreichen: durchgestrichener Text laesst sich nicht
   lesen, und genau der alte Wert ist der, den man wiedererkennen muss. Rot
   ist der falsche Ist-Zustand, gruen der richtige Soll-Zustand. */
.nlf-change {
    font-size: .78rem;
    line-height: 1.6;
    margin-bottom: .2rem;
}

.nlf-change__track {
    font-family: var(--bs-font-monospace);
    color: var(--bs-secondary-color);
}

.nlf-change__bad,
.nlf-change__good {
    display: inline-block;
    padding: 0 .4rem;
    border-radius: 1rem;
    font-family: var(--bs-font-monospace);
    font-size: .74rem;
    line-height: 1.5;
    white-space: nowrap;
}

.nlf-change__bad {
    background: rgba(220, 53, 69, .18);
    color: var(--bs-danger-text-emphasis, #ea868f);
    border: 1px solid rgba(220, 53, 69, .35);
}

.nlf-change__good {
    background: rgba(25, 135, 84, .18);
    color: var(--bs-success-text-emphasis, #75b798);
    border: 1px solid rgba(25, 135, 84, .35);
    font-weight: 600;
}

.nlf-change__arrow {
    color: var(--bs-secondary-color);
    padding: 0 .15rem;
}

.nlf-change__src {
    color: var(--bs-secondary-color);
    font-size: .72rem;
}

/* Auswahlleiste der Befunde.
   Die Zahl steht gross ganz vorn - sie ist die eine Angabe, die man beim
   Ankreuzen im Auge behaelt. Die ganze Leiste faerbt sich, sobald etwas
   ansteht; sonst uebersieht man beim Blaettern durch hundert Zeilen, dass
   noch eine Auswahl offen ist. */
.nlf-batch__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

.nlf-batch__num {
    font-size: 1.1rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    min-width: 2.2rem;
    text-align: right;
    color: var(--bs-secondary-color);
}

.nlf-batch__label {
    font-size: .82rem;
    color: var(--bs-secondary-color);
}

.nlf-batch__group {
    display: inline-flex;
    gap: .35rem;
}

.nlf-batch__spacer {
    flex: 1 1 auto;
}

.nlf-batch--active {
    border-color: var(--bs-primary);
    box-shadow: inset 3px 0 0 var(--bs-primary);
}

.nlf-batch--active .nlf-batch__num,
.nlf-batch--active .nlf-batch__label {
    color: var(--bs-body-color);
}

/* Ausgewaehlte Zeile sichtbar machen: das Kaestchen allein ist zu klein,
   um beim Ueberfliegen aufzufallen. */
tr.nlf-row--picked > td {
    background: color-mix(in srgb, var(--bs-primary) 12%, transparent);
}

tr.nlf-row--picked > td:first-child {
    box-shadow: inset 3px 0 0 var(--bs-primary);
}

/* Tooltips mit Tabelle statt einer Textzeile.
   Ein Tooltip, der nur "Kennung bestätigt" sagt, spart keinen Klick - eine
   kleine Tabelle mit Ist, Gehört und Zustand beantwortet die Frage sofort. */
.nlf-tip .tooltip-inner {
    max-width: 22rem;
    text-align: left;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .3);
    padding: .45rem .55rem;
}

.nlf-tip .tooltip-arrow::before {
    border-top-color: var(--bs-border-color);
    border-bottom-color: var(--bs-border-color);
}

.nlf-tip__head {
    font-weight: 600;
    font-size: .78rem;
    margin-bottom: .25rem;
    padding-bottom: .2rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.nlf-tip__table {
    font-size: .74rem;
    line-height: 1.45;
    border-collapse: collapse;
    width: 100%;
}

.nlf-tip__table th {
    font-weight: 400;
    color: var(--bs-secondary-color);
    padding-right: .6rem;
    white-space: nowrap;
    vertical-align: top;
    text-align: left;
}

.nlf-tip__table td {
    font-family: var(--bs-font-monospace);
    overflow-wrap: anywhere;
}

/* Aktionen unter den Befehlen eines Befundes. */
.nlf-fix__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
    margin-top: .5rem;
}

.nlf-fix__status {
    font-variant-numeric: tabular-nums;
}

/* Mitschrift eines Korrekturlaufs.
   Waechst waehrend des Laufs; gescrollt wird im Block, nicht im Dokument. */
.nlf-fix__output {
    max-height: 18rem;
    overflow: auto;
    white-space: pre;
    user-select: text;
    margin-top: .4rem;
    font-size: .72rem;
}

/* Eingangskorb: Ist gegen Soll je Datei.
   Zwei Zeilen untereinander statt zweier Spalten nebeneinander - so steht
   jeder Wert genau unter seinem Gegenstueck. */
.nlf-todo__table {
    font-size: .78rem;
    border-collapse: collapse;
    width: 100%;
}

.nlf-todo__table th {
    font-weight: 400;
    color: var(--bs-secondary-color);
    text-align: left;
    padding: .1rem .8rem .1rem 0;
    white-space: nowrap;
}

.nlf-todo__table td {
    padding: .1rem .8rem .1rem 0;
    font-family: var(--bs-font-monospace);
}

.nlf-todo__want {
    color: var(--bs-success-text-emphasis, var(--bs-success));
    font-weight: 600;
}

/* Zugeklappt, bis das Kaestchen in der Karte darueber gesetzt ist. Der
   Umschalter und der Inhalt liegen in ZWEI verschiedenen .card-body, sind
   also keine Geschwister - der Bezug muss deshalb ueber die Karte gehen. */
.nlf-todo__cmd {
    border-top: 1px solid var(--bs-border-color);
    display: none;
}

.nlf-todo:has(.nlf-fixtoggle:checked) .nlf-todo__cmd {
    display: block;
}

/* ====================================================================== */
/* Diagramme                                                              */
/*                                                                        */
/* Die Farben der Flaechen stehen im SVG (siehe app/Chart.php), weil sie  */
/* zu den Daten gehoeren. Hier steht nur, was zur DARSTELLUNG gehoert:    */
/* Schriftgroessen, Spurfarbe, Verhalten beim Ueberfahren.                */
/* ====================================================================== */

.nlf-chart {
    display: block;
    overflow: visible;
}

.nlf-chart text {
    font-family: inherit;
    fill: var(--bs-body-color);
}

.nlf-chart__label {
    font-size: 11.5px;
    fill: var(--bs-secondary-color);
}

.nlf-chart__value {
    font-size: 11.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.nlf-chart__axis {
    font-size: 10px;
    fill: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
}

/* Die Spur unter dem Balken: sie zeigt, wieviel NOCH fehlt. Ohne sie
   schwebt ein kurzer Balken im Nichts und laesst sich nicht einordnen. */
.nlf-chart__track {
    fill: var(--bs-secondary-bg);
    stroke: var(--bs-secondary-bg);
}

.nlf-chart__row {
    fill: transparent;
}

.nlf-chart a:hover .nlf-chart__row,
.nlf-chart__row:hover {
    fill: var(--bs-tertiary-bg);
}

.nlf-chart a {
    text-decoration: none;
}

.nlf-chart__col {
    transition: opacity .12s;
}

.nlf-chart__col:hover {
    opacity: .7;
}

.nlf-chart__center {
    font-size: 19px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.nlf-chart--gauge .nlf-chart__center {
    font-size: 15px;
}

.nlf-chart__centernote {
    font-size: 10px;
    fill: var(--bs-secondary-color);
}

.nlf-chart--stack {
    border-radius: 3px;
    overflow: hidden;
}

/*
 * Balken als HTML, siehe `Chart::bars()` (13.09.2026).
 *
 * Drei feste Spalten je Zeile, ueber alle Zeilen gleich: Beschriftung bis zur
 * Hoechstbreite, Spur, Wert. Nur so sind die Spuren gleich lang und die
 * Balken vergleichbar. Die Beschriftung gibt erst nach, wenn die Spur sonst
 * unter 2 rem fiele, und kuerzt dann mit Auslassungspunkten.
 */
.nlf-bars {
    display: grid;
    gap: var(--bar-gap, 8px);
}

/* Eine lange Liste rollt senkrecht, etwa 125 Jahrgaenge in der Uebersicht. */
.nlf-bars--scroll {
    max-height: var(--bar-max-height);
    overflow-y: auto;
    padding-right: .35rem;
    scrollbar-gutter: stable;
}

.nlf-bars__row {
    display: grid;
    grid-template-columns: minmax(0, var(--bar-label, 150px)) minmax(2rem, 1fr) var(--bar-value, 78px);
    column-gap: .5rem;
    align-items: center;
    min-height: var(--bar-row, 22px);
    padding: 0 .25rem;
    border-radius: 4px;
    font-size: .75rem;
    color: inherit;
    text-decoration: none;
}

a.nlf-bars__row:hover {
    background: var(--bs-tertiary-bg);
    color: inherit;
}

.nlf-bars__label {
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--bs-secondary-color);
}

/* Die Spur zeigt, wieviel NOCH fehlt, wie beim SVG vorher. */
.nlf-bars__track {
    display: block;
    height: var(--bar-track, 16px);
    border-radius: 3px;
    background: var(--bs-secondary-bg);
    overflow: hidden;
}

.nlf-bars__fill {
    display: block;
    height: 100%;
    border-radius: 3px;
}

.nlf-bars__value {
    text-align: right;
    white-space: nowrap;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/*
 * Eine Liste, die die Hoehe ihrer Karte fuellt. Die Jahrgaenge stehen neben
 * drei Karten fester Hoehe und rollen im Rest; allein in einer Zeile bleiben
 * 12 rem. Die Karte braucht dafuer `card-body d-flex flex-column`.
 */
.nlf-bars--fill {
    flex: 1 1 0;
    min-height: 12rem;
    max-height: none;
}

/*
 * Auslastung in der Uebersicht (13.09.2026): die Karte steht in zwei Dritteln
 * der Breite, Prozessor links, Ressourcen rechts. Unter 48 rem Kartenbreite
 * stehen beide untereinander, wie auf /admin/system.
 *
 * Die Schwelle stand zuerst bei 44 rem, dann bei 56 rem. Mit 56 rem stand die
 * Karte bei 1280 px (800 px Inhalt) untereinander, 678 px hoch, und die
 * Systemkarte daneben verteilte sechs Zeilen ueber dieselbe Hoehe. Mit 44 rem
 * brachen dort die Zeilen der Laufwerke um ("schreibt" ueber "0"). Deshalb
 * 48 rem und die engere Ressourcenzelle darunter.
 */
/*
 * Zwei BENANNTE Container. Ohne Namen fragt eine Regel den naechsten Container
 * ueber sich: als die Ressourcenzelle einer wurde, mass `.nlf-load .nlf-res` ihre
 * 23 rem statt der 50 rem der Karte, und ueber "Arbeitsspeicher" stand wieder die
 * obere Linie (13.09.2026, gesehen auf dem Bildschirmfoto bei 1280 px).
 */
.nlf-load-host { container: nlf-load / inline-size; }

.nlf-load {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
}

/* Die Ressourcenzelle misst ihre eigene Breite: unter 25 rem rueckt die Namensspalte zusammen. */
.nlf-load > #nlf-resources { container: nlf-res / inline-size; }

/*
 * Mit `#nlf-resources` davor: die Grundregel `.nlf-res__row` steht weiter unten in
 * dieser Datei und gewaenne bei gleicher Gewichtung.
 */
/*
 * 5,8 rem und etwas kleinere Namen: mit 5,4 rem stand bei 1280 px "Arbeitsspeic…"
 * (13.09.2026). "Arbeitsspeicher" braucht bei 0,72 rem rund 88 px.
 */
@container nlf-res (max-width: 25rem) {
    #nlf-resources .nlf-res__row {
        grid-template-columns: minmax(0, 5.8rem) minmax(2rem, 1fr) 2.4rem;
        column-gap: .4rem;
    }
    #nlf-resources .nlf-res__name { font-size: .72rem; }
    #nlf-resources .nlf-res__detail { font-size: .64rem; }
}

@container nlf-load (min-width: 48rem) {
    .nlf-load {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        column-gap: 1.25rem;
    }
    /*
     * Die Trennlinie gehoert an die Rasterzelle, nicht an die Liste: so reicht sie
     * bis zum Boden der Karte. An `.nlf-res` endete sie nach "Netz eth0".
     * M. Martin am 13.09.2026: "die Zwischenlinie bei Arbeitsspeicher länger nach
     * unten".
     */
    .nlf-load > #nlf-resources {
        padding-left: 1.25rem;
        border-left: 1px solid var(--bs-border-color);
    }
    .nlf-load .nlf-res {
        margin-top: 0;
        padding-top: 0;
        border-top: 0;
    }
}

/*
 * Die Uebersicht fuellt ihre Zeilen (13.09.2026). M. Martin: "Startseite
 * Design+Layout (Flex)". Gemessen vorher bei 1920 px: rechts endeten Auslastung
 * und Eingangskorb 122 px hoeher als links, und in den Vorraeten blieben unten
 * 78 px leer.
 *
 * Beide Spalten der oberen Zeile sind Flex-Spalten (`nlf-stack` in
 * dashboard.php). Rechts nimmt die Auslastung den Rest, links die Cron-Karte.
 *
 * WAS WAECHST. Die erste Fassung dehnte die Prozessorbalken auf die Hoehe der
 * Spalte, bei 1920 px 357 px. M. Martin: "Sieht nicht gut aus. Die großen
 * Prozessor-Charts." Ein Balken fuer 76 % sagt bei 357 px nicht mehr als bei
 * 48 px. Die Balken behalten `--nlf-bar`; den Platz fuellt der Verlauf der
 * letzten zehn Minuten darunter (`.nlf-cpu-history`), eine Zeitreihe verliert
 * durch Hoehe nichts.
 */

/*
 * Die drei Anteile der Prozessorzeit, ueberall dieselbe Farbe: Balken, Legende,
 * Verlauf. Das Orange des hellen Themas faellt vor dunklem Grund aus dem
 * Helligkeitsband (OKLCH L 0,727, erlaubt 0,48 bis 0,67; geprueft mit
 * validate_palette.js). #c6800c liegt darin und haelt zum Rot Delta E 16,7,
 * bei Rot-Gruen-Schwaeche 7,6: zulaessig mit zweiter Kennung, hier Legende,
 * feste Stapelfolge und Tooltip.
 */
:root {
    --nlf-cpu-user: var(--bs-primary);
    --nlf-cpu-sys: #fd7e14;
    --nlf-cpu-io: var(--bs-danger);
}
[data-bs-theme="dark"] {
    --nlf-cpu-sys: #c6800c;
}
.nlf-load-host {
    display: flex;
    flex-direction: column;
}

/*
 * Der Mehrplatz der Karte geht an den Prozessorbereich (erste Rasterzeile), nicht
 * an die Ressourcen: dort waechst der Verlauf.
 */
.nlf-load {
    flex: 1 1 auto;
    grid-template-rows: 1fr auto;
}

.nlf-load__cpu {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* ---------------------------------------------- Verlauf der Auslastung */

.nlf-cpu-history {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    gap: .25rem;
    min-height: 7rem;
    margin-top: .9rem;
}

.nlf-cpu-history__head,
.nlf-cpu-history__time {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    font-size: .68rem;
    color: var(--bs-secondary-color);
}

.nlf-cpu-history__stats {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Die Zeichenflaeche traegt nichts zur Hoehe bei, sie nimmt, was die Karte hat. */
.nlf-cpu-history__plot {
    position: relative;
    flex: 1 1 auto;
    min-height: 4.5rem;
    outline-offset: 2px;
}

.nlf-cpu-history__plot > svg {
    position: absolute;
    inset: 0;
    overflow: visible;
}

/* Gitter und Achse: Haarlinien, durchgezogen, eine Stufe vom Grund. */
.nlf-cpu-history__grid { stroke: var(--bs-border-color); stroke-width: 1; opacity: .6; }
.nlf-cpu-history__axis { stroke: var(--bs-border-color); stroke-width: 1; }
.nlf-cpu-history__tick { fill: var(--bs-secondary-color); font-size: 10px; font-variant-numeric: tabular-nums; }

.nlf-cpu-history__area { stroke: none; fill-opacity: .22; }
.nlf-cpu-history__area--user { fill: var(--nlf-cpu-user); }
.nlf-cpu-history__area--sys  { fill: var(--nlf-cpu-sys); }
.nlf-cpu-history__area--io   { fill: var(--nlf-cpu-io); }

.nlf-cpu-history__line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.nlf-cpu-history__line--user { stroke: var(--nlf-cpu-user); }
.nlf-cpu-history__line--sys  { stroke: var(--nlf-cpu-sys); }
.nlf-cpu-history__line--io   { stroke: var(--nlf-cpu-io); }

.nlf-cpu-history__cross {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--bs-secondary-color);
    pointer-events: none;
}

.nlf-cpu-history__tip {
    position: absolute;
    top: .25rem;
    z-index: 2;
    padding: .3rem .5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm, .25rem);
    background: var(--bs-body-bg);
    font-size: .7rem;
    line-height: 1.35;
    white-space: nowrap;
    pointer-events: none;
}

.nlf-cpu-history__tip-head { color: var(--bs-secondary-color); margin-bottom: .1rem; }
.nlf-cpu-history__tip strong { font-variant-numeric: tabular-nums; margin-right: .25rem; }

/* Linienkennung im Tooltip, kein Kasten. */
.nlf-cpu-history__key {
    display: inline-block;
    width: .75rem;
    height: 2px;
    margin-right: .35rem;
    vertical-align: middle;
}
.nlf-cpu-history__key--user { background: var(--nlf-cpu-user); }
.nlf-cpu-history__key--sys  { background: var(--nlf-cpu-sys); }
.nlf-cpu-history__key--io   { background: var(--nlf-cpu-io); }

/*
 * Pfadkarten auf /admin/system (13.09.2026): zwei Spalten, jede Karte so hoch wie
 * ihr Inhalt, die Reihenfolge von PathMap::GROUPS bleibt. Vorher standen sie
 * paarweise in einer Zeile mit gleicher Hoehe; "Anwendung" mit vier Eintraegen
 * zog sich auf die Hoehe von "Bestand" mit zehn und stand bei 1920 px rund 300 px
 * leer.
 */
.nlf-path-columns { column-gap: 1rem; }
.nlf-path-columns > .card {
    break-inside: avoid;
    margin-bottom: 1rem;
}
@media (min-width: 1200px) {
    .nlf-path-columns { column-count: 2; }
}

/*
 * Aufgaben auf /admin/cron (13.09.2026): je Aufgabe ein `tbody` mit zwei Zeilen.
 * Oben Titel, Plan, Art, Laeufe und Schalter, darunter die Beschreibung ueber
 * alle Spalten. M. Martin: "Hier kann die Beschreibung auch über die gesamte
 * Breite gehen. Spart eine Textzeile pro Aufgabe." Zwischen den beiden Zeilen
 * einer Aufgabe steht keine Linie, zwischen zwei Aufgaben schon.
 */
.nlf-tasks > .nlf-task > tr:first-child:not(:last-child) > td {
    border-bottom-width: 0;
    padding-bottom: .1rem;
}
.nlf-tasks > .nlf-task > .nlf-task__note > td {
    padding-top: 0;
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
/*
 * Die Aufgabentabelle auf /admin/cron teilt die Breite fest auf. Vorher wuchs
 * die Spalte Art auf die laengsten Optionen (583 px bei 1920 px Fensterbreite),
 * und bei 1280 px rollte die Tabelle 178 px zur Seite. Unter 64rem rollt sie in
 * ihrem Kasten.
 */
.nlf-tasks {
    table-layout: fixed;
    min-width: 64rem;
}
.nlf-task__options {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

/*
 * Letzte Laeufe auf /admin/cron: bis zu 200 Zeilen in einer Box, die rollt.
 * Der Kopf bleibt stehen und deckt die Zeilen darunter ab.
 */
.nlf-runs {
    max-height: 22rem;
    overflow-y: auto;
}

/*
 * Vorschau im Reiter Probe: vor dem ersten Fall stand dort eine schwarze Flaeche
 * von 14rem (_todo.txt Punkt 15). app.js setzt nlf-pb-preview--on beim Start.
 */
.nlf-pb-preview:not(.nlf-pb-preview--on) video,
.nlf-pb-preview:not(.nlf-pb-preview--on) .video-js {
    display: none;
}
.nlf-runs > .table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 1;
    background-color: var(--bs-card-bg, var(--bs-body-bg));
    box-shadow: inset 0 -1px 0 var(--bs-border-color);
}

/*
 * Der Verlauf der Cron-Laeufe fuellt die Hoehe, die seine Karte ohnehin hat.
 * Absolut gelegt, damit er nichts zur Hoehe beitraegt: mit `height: auto`
 * rechnete das SVG seine Hoehe aus viewBox 260 x 46 und 590 px Breite, die
 * Karte wuchs um 58 px, und die Auslastung zog mit (Balken 357 px, 13.09.2026).
 */
.nlf-grow-chart {
    position: relative;
    flex: 1 1 0;
    min-height: 46px;
}
.nlf-grow-chart .nlf-chart-roll {
    position: absolute;
    inset: 0;
    padding-bottom: 0;
}
.nlf-grow-chart .nlf-chart-roll > .nlf-chart--spark {
    width: 100%;
    height: 100%;
}

/* Legende: Punkt, Name, Wert, Anteil - in dieser Reihenfolge, weil man von
   links nach rechts liest und der Name die Frage ist, der Wert die Antwort. */
.nlf-legend li {
    display: flex;
    align-items: center;
    gap: .45rem;
    padding: .12rem 0;
    font-size: .8rem;
}

.nlf-legend a {
    display: flex;
    align-items: center;
    gap: .45rem;
    width: 100%;
    color: inherit;
    text-decoration: none;
    border-radius: 3px;
    padding: 0 .2rem;
    margin: 0 -.2rem;
}

.nlf-legend a:hover {
    background: var(--bs-tertiary-bg);
}

.nlf-legend__dot {
    width: .6rem;
    height: .6rem;
    border-radius: 2px;
    flex-shrink: 0;
}

.nlf-legend__label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nlf-legend__value {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

/* 3,2rem reichten fuer "0,64 %", nicht fuer "97,44 %" - das Prozentzeichen
   rutschte in die naechste Zeile und die Legende wurde zweizeilig. Breite
   nach dem laengsten moeglichen Wert, und umbrechen darf sie gar nicht. */
.nlf-legend__share {
    font-variant-numeric: tabular-nums;
    color: var(--bs-secondary-color);
    width: 4.2rem;
    text-align: right;
    flex-shrink: 0;
    white-space: nowrap;
}

/* ====================================================================== */
/* Kennzahlen-Kacheln                                                     */
/* ====================================================================== */

.nlf-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: .75rem;
    margin-bottom: 1rem;
}

.nlf-stat {
    display: block;
    position: relative;
    padding: .8rem .9rem .7rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    background: var(--bs-body-bg);
    color: inherit;
    text-decoration: none;
    overflow: hidden;
}

/* Der farbige Streifen links ordnet die Kachel einer Sache zu, ohne dass
   die ganze Kachel eingefaerbt werden muss - eingefaerbte Flaechen lesen
   sich als Warnung, und das sind die meisten Kennzahlen nicht. */
.nlf-stat::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    background: var(--nlf-stat-color, var(--bs-primary));
}

a.nlf-stat:hover {
    border-color: var(--nlf-stat-color, var(--bs-primary));
}

.nlf-stat__label {
    font-size: .74rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--bs-secondary-color);
    margin-bottom: .15rem;
}

.nlf-stat__value {
    font-size: 1.75rem;
    line-height: 1.1;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.nlf-stat__unit {
    font-size: .95rem;
    font-weight: 400;
    color: var(--bs-secondary-color);
}

.nlf-stat__note {
    font-size: .76rem;
    color: var(--bs-secondary-color);
    margin-top: .2rem;
}

.nlf-stat__spark {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 45%;
    opacity: .5;
    pointer-events: none;
}

/* ====================================================================== */
/* Abschnitte und Karten                                                  */
/* ====================================================================== */

/* Eine Ueberschrift, die eine Gruppe von Karten anfuehrt. Sie traegt die
   Frage, die die Karten darunter beantworten. */
.nlf-section {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    margin: 1.4rem 0 .6rem;
}

.nlf-section:first-child {
    margin-top: 0;
}

.nlf-section__title {
    font-size: .95rem;
    font-weight: 600;
    margin: 0;
}

.nlf-section__note {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}

.nlf-section__line {
    flex: 1 1 auto;
    height: 1px;
    background: var(--bs-border-color);
}

/* Kartenkoepfe waren fett und laut. Leiser, dafuer mit klarer Trennlinie -
   die Karte selbst soll auffallen, nicht ihre Beschriftung. */
.nlf-admin .card-header {
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .01em;
    background: transparent;
    padding: .55rem .85rem;
}

.nlf-admin .card {
    border-radius: var(--bs-border-radius-lg);
}

.nlf-admin .card-header .btn-sm,
.nlf-admin .card-header .form-select-sm {
    font-size: .75rem;
    padding-block: .1rem;
}

/* Zahlenspalten sollen untereinander stehen - sonst tanzen die Ziffern. */
.nlf-admin td.text-end,
.nlf-admin th.text-end {
    font-variant-numeric: tabular-nums;
}

/* ====================================================================== */
/* Kopfzeile: Ausrichtung                                                 */
/* ====================================================================== */

/* Marke und Menue trennen. Ohne Trennung liest sich "StreamMaster Admin
   Übersicht" als eine einzige Wortkette - der Name der Anwendung und der
   erste Menuepunkt gehoeren aber nicht zusammen. */
.nlf-admin .navbar-brand {
    padding-right: 1rem;
    margin-right: 1rem;
    border-right: 1px solid var(--bs-border-color);
}

/* Die Elemente rechts hatten drei verschiedene Hoehen (19, 31, 40 px) und
   standen dadurch trotz gleicher Mitte unruhig nebeneinander. Eine
   gemeinsame Hoehe bindet sie zu einer Gruppe. */
.nlf-admin .navbar .badge,
.nlf-admin .navbar .btn {
    display: inline-flex;
    align-items: center;
    height: 1.9rem;
    line-height: 1;
}

/* Der Pfeil am Aufklappmenue: Bootstrap setzt ihn mit `vertical-align:
   .255em` - dieselbe Falle wie beim Markenpunkt, nur kleiner. */
.nlf-admin .navbar-nav .dropdown-toggle {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}

.nlf-admin .navbar-nav .dropdown-toggle::after {
    margin: 0;
    vertical-align: 0;
}

/* Der aktive Punkt bekommt eine Unterkante statt nur fetter Schrift -
   fette Schrift verbreitert den Punkt und verschiebt alle folgenden. */
.nlf-admin .navbar-nav > .nav-item > .nav-link.active {
    box-shadow: inset 0 -2px 0 var(--bs-primary);
}

/* Die Hoechstwertlinie im Saeulendiagramm: sichtbar genug, um den Bezug zu
   stiften, leise genug, um nicht mit den Daten zu konkurrieren. */
.nlf-chart__gridline {
    stroke: var(--bs-border-color);
    stroke-width: 1;
    stroke-dasharray: 3 3;
}

/* ====================================================================== */
/* Aufklappbare Karte                                                     */
/*                                                                        */
/* Fuer Auskuenfte, die man EINMAL braucht - die Crontab-Zeile etwa. Sie  */
/* standen bisher ganz oben und schoben das Taegliche nach unten.         */
/* ====================================================================== */

.nlf-details > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: .4rem;
}

.nlf-details > summary::-webkit-details-marker {
    display: none;
}

/* Ein eigener Pfeil, der sich dreht - der eingebaute sitzt je nach Browser
   woanders und laesst sich nicht ausrichten. */
.nlf-details > summary::before {
    content: "";
    width: .45rem;
    height: .45rem;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    transition: transform .15s;
    opacity: .6;
    flex-shrink: 0;
}

.nlf-details[open] > summary::before {
    transform: rotate(45deg);
}

.nlf-details > summary:hover {
    background: var(--bs-tertiary-bg);
}

/* Karten-Kopfzeile mit Trennlinie erst, wenn etwas darunter steht. */
.nlf-details:not([open]) > summary {
    border-bottom: 0;
}

/* Der zugeklappte Rest eines Detailblocks. Er soll leise sein - wer ihn
   braucht, sucht ihn; wer ihn nicht braucht, soll ihn nicht lesen muessen. */
.nlf-detail__more > summary {
    cursor: pointer;
    font-size: .72rem;
    color: var(--bs-secondary-color);
    list-style: none;
    padding: .1rem 0;
}

.nlf-detail__more > summary::-webkit-details-marker {
    display: none;
}

.nlf-detail__more > summary::before {
    content: "▸ ";
}

.nlf-detail__more[open] > summary::before {
    content: "▾ ";
}

.nlf-detail__more > summary:hover {
    color: var(--bs-body-color);
}

/* Die Verfahren auf der Katalogkarte: leiser als Jahr und Größe, weil sie
   eine andere Frage beantworten - nicht "was ist das", sondern "läuft das
   hier". Wer danach filtert, sucht sie; wer blättert, überliest sie. */
.nlf-card__tech {
    font-size: .68rem;
    color: var(--bs-tertiary-color, var(--bs-secondary-color));
    font-family: var(--bs-font-monospace);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Die Filterleiste des Katalogs: sie wuchs von vier auf sieben Felder und
   brach dabei auf drei ungleiche Zeilen um. Ein Raster mit Mindestbreite
   ordnet sich selbst - dieselbe Regel wie bei den Kennzahlkacheln. */
.nlf-filter-bar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
    gap: .6rem .75rem;
    align-items: end;
    margin-bottom: 1rem;
}

/* Die Suche ist das erste Feld und darf zwei Spalten breit sein - sie
   trägt einen Satz, die anderen ein Wort. */
.nlf-filter-bar__wide {
    grid-column: span 2;
}

@media (max-width: 640px) {
    .nlf-filter-bar__wide {
        grid-column: span 1;
    }
}

.nlf-filter-bar label {
    display: block;
    font-size: .78rem;
    margin-bottom: .15rem;
    color: var(--bs-secondary-color);
}

/* Die technische Einschränkung auf der Befundseite. Sie steht unter den
   Kategorien, weil sie deren Auswahl weiter eingrenzt - nicht daneben, wo
   sie wie eine zweite gleichrangige Wahl aussähe. */
.nlf-techbar {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    gap: .5rem .9rem;
}

.nlf-techbar label {
    display: block;
    font-size: .74rem;
    color: var(--bs-secondary-color);
}

.nlf-techbar select {
    min-width: 8rem;
    margin-top: .1rem;
}

.nlf-techbar__note {
    font-size: .78rem;
    color: var(--bs-secondary-color);
    align-self: center;
    max-width: 46rem;
}

/* ====================================================================== */
/* Cover-Abgleich                                                         */
/*                                                                        */
/* Zwei Bilder nebeneinander, damit man sie VERGLEICHEN kann - das ist    */
/* der ganze Zweck der Seite. Untereinander müsste man scrollen und       */
/* hätte nie beide im Blick.                                              */
/* ====================================================================== */

.nlf-covers {
    display: grid;
    /*
       `min(23rem, 100%)` statt `23rem`: 23 rem sind 368 px, und auf einem
       Samsung S8 mit 360 px lief die Seite dadurch um 28 px waagerecht ueber
       (gemessen am 9.9.2026). Die Mindestbreite darf nie groesser sein als
       der Platz, sonst ist sie keine Mindestbreite, sondern eine Vorgabe.
    */
    grid-template-columns: repeat(auto-fill, minmax(min(23rem, 100%), 1fr));
    gap: .8rem;
}

/* Die Gruppenüberschrift läuft über die ganze Breite - sie trennt, was
   zusammengehört, und das sind bei geteilten Bildern mehrere Karten. */
.nlf-covers__group {
    grid-column: 1 / -1;
    font-size: .82rem;
    color: var(--bs-secondary-color);
    padding: .5rem 0 .1rem;
    border-top: 1px solid var(--bs-border-color);
}

.nlf-covers__group:first-child {
    border-top: 0;
    padding-top: 0;
}

.nlf-cover {
    display: flex;
    gap: .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    padding: .6rem;
    background: var(--bs-body-bg);
}

.nlf-cover__pair {
    display: flex;
    gap: .3rem;
    flex-shrink: 0;
}

.nlf-cover__fig {
    margin: 0;
    width: 4.6rem;
}

.nlf-cover__fig img {
    width: 100%;
    aspect-ratio: 2 / 3;
    object-fit: cover;
    border-radius: 3px;
    background: var(--bs-tertiary-bg);
    display: block;
}

/*
 * Das Vorschaubild in den Nachtragslisten.
 *
 * Schmaler als die Kacheln des Vergleichs oben: dort stehen zwei Bilder
 * nebeneinander und werden angesehen, hier steht eines in einer
 * Tabellenzeile und beantwortet nur die Frage "gehoert das dazu?".
 */
.nlf-fetch__thumb {
    cursor: zoom-in;
    width: 2.6rem;
    aspect-ratio: 2 / 3;
    object-fit: cover;
    border-radius: 3px;
    background: var(--bs-tertiary-bg);
    display: block;
}

.nlf-cover__fig figcaption {
    font-size: .64rem;
    color: var(--bs-secondary-color);
    text-align: center;
    margin-top: .15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nlf-cover__none {
    aspect-ratio: 2 / 3;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-size: .64rem;
    color: var(--bs-secondary-color);
    background: var(--bs-tertiary-bg);
    border-radius: 3px;
}

.nlf-cover__body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .2rem;
}

.nlf-cover__title {
    font-weight: 600;
    font-size: .88rem;
    color: inherit;
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nlf-cover__title:hover {
    text-decoration: underline;
}

.nlf-cover__meta {
    font-size: .74rem;
    color: var(--bs-secondary-color);
}

.nlf-cover__path {
    font-size: .68rem;
    color: var(--bs-tertiary-color, var(--bs-secondary-color));
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nlf-cover__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
    margin-top: auto;
    padding-top: .3rem;
}

/* ====================================================================== */
/* Titelseite: die Faktenspalte                                           */
/*                                                                        */
/* Sie stand vorher leer - unter dem Poster kamen mehrere hundert Pixel   */
/* Nichts, während rechts der Text lief. Was man NACHSCHLÄGT statt liest, */
/* gehört hierher: Laufzeit, Freigabe, Sprachen, Umfang.                  */
/* ====================================================================== */

/* Zwei Spalten: Bezeichnung links, Wert RECHTS ausgerichtet.
   Untereinander brauchte dieselbe Auskunft die doppelte Höhe, und die
   Werte standen linksbündig unter ihren Bezeichnungen - zwei Kanten, wo
   eine genügt. `auto 1fr` lässt die linke Spalte so breit werden, wie ihr
   längstes Wort es verlangt. */
.nlf-facts {
    margin: 0;
    font-size: .8rem;
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: .6rem;
    row-gap: .25rem;
    align-items: baseline;
}

.nlf-facts dt {
    font-weight: 400;
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}

.nlf-facts dd {
    margin: 0;
    text-align: right;
    /* Lange Werte ("ger, eng, fra") dürfen umbrechen, statt die Spalte
       aufzublähen - dann steht die zweite Zeile ebenfalls rechts. */
    overflow-wrap: anywhere;
}

/* Bewertungen als Zahl mit Quelle darunter - nicht als Abzeichen in einer
   Reihe mit den Genres. Eine Bewertung ist eine Zahl, kein Schlagwort. */
.nlf-ratings {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}

.nlf-rating {
    flex: 1 1 3.5rem;
    text-align: center;
    padding: .3rem .2rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background: var(--bs-tertiary-bg);
}

.nlf-rating__value {
    display: block;
    font-size: 1.05rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.nlf-rating__source {
    display: block;
    font-size: .64rem;
    color: var(--bs-secondary-color);
}

/* Sprachhinweis beim Cover-Abgleich. Die Sprache entscheidet hier mehr als
   der Bildabstand: im Dateisystem stehen die deutschen Cover, ein Dienst
   liefert oft das englische. */
.nlf-cover__warn,
.nlf-cover__ok {
    font-size: .72rem;
    padding: .2rem .4rem;
    border-radius: var(--bs-border-radius);
    line-height: 1.3;
}

.nlf-cover__warn {
    background: var(--bs-warning-bg-subtle, rgba(255, 193, 7, .15));
    color: var(--bs-warning-text-emphasis, var(--bs-warning));
    border: 1px solid var(--bs-warning-border-subtle, transparent);
}

.nlf-cover__ok {
    color: var(--bs-success-text-emphasis, var(--bs-success));
}

/* ====================================================================== */
/* Cover groß vergleichen                                                 */
/* ====================================================================== */

/*
 * Die kleinen Bilder sind Knöpfe - aber sie sollen nicht danach aussehen.
 * Kein Rahmen, kein Polster, nur der Zeiger und ein Hinweis beim Überfahren.
 */
.nlf-cover__zoom {
    display: block;
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
    width: 100%;
    border-radius: var(--radius-sm, 3px);
}

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

.nlf-cover__zoom img {
    transition: transform .12s ease-out, box-shadow .12s ease-out;
}

.nlf-cover__zoom:hover img {
    transform: scale(1.06);
    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .35);
}

/*
 * Der Dialog selbst.
 *
 * `display` gehört an `[open]`, nicht an das Element: ein `<dialog>` ist von
 * sich aus `display:none`, und eine Regel ohne `[open]` macht es dauerhaft
 * sichtbar - auch ungeöffnet.
 */
.nlf-zoom {
    border: 0;
    padding: 0;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    border-radius: var(--radius-lg, .5rem);
    box-shadow: 0 1rem 3rem rgba(0, 0, 0, .5);
    max-width: min(96vw, 1600px);
    max-height: 94vh;
    width: min(96vw, 1600px);
}

.nlf-zoom[open] {
    display: flex;
    flex-direction: column;
}

.nlf-zoom::backdrop {
    background: rgba(0, 0, 0, .75);
}

.nlf-zoom__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--bs-border-color);
    flex: 0 0 auto;
}

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

.nlf-zoom__nav {
    display: flex;
    align-items: center;
    gap: .4rem;
    flex: 0 0 auto;
}

/*
 * Zwei gleich breite Spalten, und die Bilder passen sich der HÖHE an.
 *
 * `min-height: 0` auf dem Kind ist der Punkt, an dem es sonst scheitert:
 * ein Flex-Element schrumpft von sich aus nicht unter seinen Inhalt, und
 * ein hohes Poster sprengt dann den Dialog nach unten hinaus.
 */
.nlf-zoom__pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    padding: 1rem;
    min-height: 0;
    flex: 1 1 auto;
}

.nlf-zoom__fig {
    margin: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
    gap: .5rem;
}

.nlf-zoom__fig img {
    min-height: 0;
    flex: 1 1 auto;
    width: 100%;
    object-fit: contain;
    background: var(--bs-tertiary-bg);
    border-radius: var(--radius-sm, 3px);
}

.nlf-zoom__fig figcaption {
    text-align: center;
    font-size: .85rem;
    color: var(--bs-secondary-color);
    flex: 0 0 auto;
}

/*
 * Die Arbeitsflaeche unter den Bildern.
 *
 * Links die Angaben, rechts der Knopf. Sie bleibt stehen, waehrend die
 * Bilder darueber die Hoehe fuellen - deshalb `flex: 0 0 auto`.
 */
.nlf-zoom__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 1rem;
    border-top: 1px solid var(--bs-border-color);
    flex: 0 0 auto;
}

.nlf-zoom__facts {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem 1.2rem;
    color: var(--bs-secondary-color);
    min-width: 0;
}

.nlf-zoom__facts code {
    word-break: break-all;
}

.nlf-zoom__actions {
    display: flex;
    align-items: center;
    gap: .4rem;
    flex: 0 0 auto;
}

/*
 * Ein Bild statt zweier: die Listenansicht zeigt nur das Cover des
 * Dienstes. Ohne diese Regel stuende es in einer halben Breite, und die
 * andere Haelfte bliebe leer.
 */
.nlf-zoom--single .nlf-zoom__pair {
    grid-template-columns: 1fr;
}

@media (max-width: 700px) {
    .nlf-zoom__pair {
        grid-template-columns: 1fr;
    }

    .nlf-zoom__foot {
        flex-direction: column;
        align-items: stretch;
    }
}


/* ==================================================== Auslastung je Kern ==
 *
 * Ein Balken je Kern, nebeneinander. Die Zahl der Kerne steht nicht fest -
 * `auto-fit` mit einer Mindestbreite fuellt die Zeile, ohne dass irgendwo
 * eine Acht im Code steht.
 *
 * Waagerecht und nicht senkrecht, weil die Balken damit dieselbe Grundlinie
 * teilen: ungleiche Auslastung faellt so auf, ohne dass man Zahlen liest -
 * und genau darum geht es, wenn man wissen will, ob noch ein Prozess passt.
 */
.nlf-cores {
    /*
     * Hoehe eines Balkens und Mindestbreite eines Thread-Platzes. Die kleine
     * Fassung setzt beides kleiner. Bis zum 13.09.2026 standen die Balken
     * 5 rem hoch; M. Martin: "Höhe der Balken kleiner und Text anders /
     * kleiner damit alles passt."
     */
    --nlf-bar: 3rem;
    /* 1,8 rem: zehn Threads passen in die Karte der Uebersicht bei 1280 px auf eine Zeile. */
    --nlf-slot: 1.8rem;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(4.5rem, 1fr));
    gap: .6rem;
    align-items: end;
}

.nlf-core {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    min-width: 0;
}

.nlf-core__bar {
    position: relative;
    height: var(--nlf-bar);
    border-radius: var(--bs-border-radius-sm, .25rem);
    background: var(--bs-tertiary-bg);
    overflow: hidden;
    /* Die Anteile stapeln sich von UNTEN - deshalb column-reverse. */
    display: flex;
    flex-direction: column-reverse;
}

.nlf-core__part { width: 100%; }
.nlf-core__part--user { background: var(--bs-primary); }
.nlf-core__part--sys  { background: var(--nlf-cpu-sys); }
.nlf-core__part--io   { background: var(--bs-danger); }

.nlf-core__label {
    display: flex;
    justify-content: space-between;
    gap: .2rem;
    /*
     * Eine Zeile. Mit Umbruch stand im Kernrahmen "#10" ueber "74 %", und die
     * Zeile war doppelt so hoch wie ihre Nachbarn (13.09.2026). Im Kernrahmen
     * steht deshalb nur der Wert, siehe `drawCore` in app.js.
     */
    white-space: nowrap;
    overflow: hidden;
    font-size: .64rem;
    line-height: 1.1;
    color: var(--bs-secondary-color);
}

.nlf-core__value { font-variant-numeric: tabular-nums; }

/*
 * Ab drei Vierteln wird die Zahl hervorgehoben. Der Wert ist derselbe, den
 * der Leerlauf-Fueller als Bremse benutzt - eine Anzeige, die eine andere
 * Schwelle zeigt als die, nach der gehandelt wird, stiftet Verwirrung.
 */
.nlf-core--hot .nlf-core__value { color: var(--bs-danger); font-weight: 600; }

/*
 * Sind es mehrere Sockel, wird das Raster zum Nebeneinander der Sockel; die
 * Kerne rastern INNERHALB ihres Sockels. Sonst stuenden acht Balken in einer
 * Reihe, und die Aufteilung waere nur an den Nummern zu erkennen - also gar
 * nicht.
 */
/*
 * Sockel UNTEREINANDER, nicht nebeneinander.
 *
 * Nebeneinander war die erste Fassung, und sie brauchte die halbe
 * Bildschirmbreite. In einer Spalte von drei ist dafuer kein Platz - die
 * Balken wuerden auf Streichholzbreite schrumpfen, und dann sagt die Hoehe
 * nichts mehr. Untereinander behaelt jeder Sockel die volle Spaltenbreite
 * fuer seine vier Balken.
 */
.nlf-cores--grouped {
    grid-template-columns: 1fr;
    gap: .75rem;
    align-items: stretch;
}

.nlf-socket {
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius, .375rem);
    padding: .6rem .7rem .7rem;
}

.nlf-socket__head {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin-bottom: .55rem;
}

/*
 * Name und Mittelwert brechen nie um, die Notiz dazwischen darf schrumpfen.
 * In der Uebersicht stand "Sockel" ueber "0" und "77" ueber "%" (13.09.2026).
 */
.nlf-socket__name { font-weight: 600; font-size: .85rem; white-space: nowrap; flex-shrink: 0; }
.nlf-socket__note { min-width: 0; font-size: .7rem; color: var(--bs-secondary-color); }

/* Der Sockelmittelwert nach rechts - dort, wo auch bei den Kernen die
   Prozentzahl steht. */
.nlf-socket__busy {
    margin-left: auto;
    flex-shrink: 0;
    white-space: nowrap;
    font-size: .85rem;
    font-variant-numeric: tabular-nums;
    color: var(--bs-secondary-color);
}

.nlf-socket__cores {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(3.2rem, 1fr));
    gap: .5rem;
    align-items: end;
}

/*
 * Kerne mit ihren Threads (13.09.2026).
 *
 * Das Raster rechnet in Thread-Plaetzen: jede Spalte ist ein Platz, und ein
 * Kernrahmen spannt so viele Spalten, wie er Plaetze hat (`grid-column` setzt
 * app.js). Die Kerne teilen sich die Breite also nach ihrem Anteil, jeder
 * Thread ist gleich breit, und umgebrochen wird erst, wenn ein Platz schmaler
 * als `--nlf-slot` wuerde. Die erste Fassung gab jedem Kern 6,6 rem; in der
 * Uebersicht standen fuenf Kerne wie fuenf Kacheln da.
 */
.nlf-socket__cores--phys {
    grid-template-columns: repeat(auto-fit, minmax(var(--nlf-slot), 1fr));
    gap: .35rem .3rem;
    align-items: stretch;
}

.nlf-phys {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    min-width: 0;
    padding: .2rem .25rem .25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm, .25rem);
}

/* Gestrichelt: dem Behaelter fehlt ein Thread dieses Kerns. */
.nlf-phys--half { border-style: dashed; }

.nlf-phys__head {
    display: flex;
    justify-content: space-between;
    gap: .2rem;
    font-size: .65rem;
    line-height: 1.1;
    color: var(--bs-secondary-color);
    white-space: nowrap;
    overflow: hidden;
}

.nlf-phys__mean { font-variant-numeric: tabular-nums; font-weight: 600; }

/*
 * Ein schmaler Rahmen kuerzt "Kern 0" zu "K0". In der Uebersicht bei 1280 px
 * war er 66 px breit, und vom Mittel blieb "27 '" stehen (13.09.2026).
 */
.nlf-phys { container-type: inline-size; }
.nlf-phys__abbr { display: none; }
@container (max-width: 4.8rem) {
    .nlf-phys__word { display: none; }
    .nlf-phys__abbr { display: inline; }
}

.nlf-phys__threads {
    display: grid;
    gap: .2rem;
    align-items: start;
}

/* Im Kernrahmen steht unter dem Balken nur der Wert, mittig. */
.nlf-phys .nlf-core__label { justify-content: center; }

/* Der Platz des fehlenden Threads: so hoch wie ein Balken, ohne Wert. */
.nlf-phys__missing {
    height: var(--nlf-bar);
    border: 1px dashed var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm, .25rem);
}

/*
 * Die kleine Fassung - fuer Seiten, auf denen die Auslastung Beiwerk ist.
 *
 * Auf der Systemseite stand dieselbe Anzeige wie auf der Uebersicht, nur
 * ueber die volle Breite und mehrere hundert Pixel hoch. Wer diese Seite
 * oeffnet, sucht Werkzeuge und Pfade; die Balken soll er im Blick behalten,
 * nicht durchscrollen muessen.
 */
.nlf-cores--klein {
    --nlf-bar: 1.7rem;
    --nlf-slot: 1.9rem;
    gap: .4rem;
}
.nlf-cores--klein .nlf-socket { padding: .35rem .45rem .45rem; }
.nlf-cores--klein .nlf-socket__head { margin-bottom: .3rem; }
.nlf-cores--klein .nlf-socket__name { font-size: .75rem; }
.nlf-cores--klein .nlf-socket__note,
.nlf-cores--klein .nlf-socket__busy { font-size: .7rem; }
.nlf-cores--klein .nlf-socket__cores {
    grid-template-columns: repeat(auto-fit, minmax(2.2rem, 1fr));
    gap: .3rem;
}
.nlf-cores--klein .nlf-core__label { font-size: .6rem; }
.nlf-cores--klein .nlf-socket__cores--phys {
    grid-template-columns: repeat(auto-fit, minmax(var(--nlf-slot), 1fr));
    gap: .3rem .25rem;
}
.nlf-cores--klein .nlf-phys { padding: .15rem .2rem .2rem; gap: .15rem; }
.nlf-cores--klein .nlf-phys__head { font-size: .6rem; }

.nlf-cores__key {
    display: inline-block;
    width: .75rem;
    height: .75rem;
    border-radius: 2px;
    vertical-align: -1px;
}
.nlf-cores__key--user { background: var(--bs-primary); }
.nlf-cores__key--sys  { background: var(--nlf-cpu-sys); }
.nlf-cores__key--io   { background: var(--bs-danger); }

/*
 * Ressourcen unter den Prozessorbalken (13.09.2026).
 *
 * Eine Zeile je Wert: Name, Balken, Zahl; darunter klein die Einzelheiten.
 * Waagerechte Balken halten die Karte niedrig: Arbeitsspeicher, Grafikeinheit,
 * drei Laufwerke und das Netz brauchen in der Uebersicht rund 13 Zeilen.
 */
.nlf-res {
    display: grid;
    gap: .45rem;
    margin-top: .8rem;
    padding-top: .7rem;
    border-top: 1px solid var(--bs-border-color);
}

.nlf-res__row {
    display: grid;
    grid-template-columns: minmax(0, 6.4rem) minmax(2.5rem, 1fr) 2.6rem;
    column-gap: .5rem;
    row-gap: .15rem;
    align-items: center;
    font-size: .75rem;
    line-height: 1.2;
}

.nlf-res__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.nlf-res__meter {
    display: flex;
    min-width: 0;
    height: .45rem;
    border-radius: 999px;
    background: var(--bs-tertiary-bg);
    overflow: hidden;
}

.nlf-res__fill { background: var(--bs-primary); }
/* Cache: belegt, aber freigebbar. Heller als das, was Programme halten. */
.nlf-res__fill--cache { background: var(--bs-primary-border-subtle); }

/* Rot ab 90 % belegt (Speicher, Laufwerk) oder 75 % Rechenzeit (Grafik), wie bei den Kernen. */
.nlf-res__row--hot > .nlf-res__meter .nlf-res__fill:first-child,
.nlf-res__engine--hot .nlf-res__fill { background: var(--bs-danger); }
.nlf-res__row--hot > .nlf-res__value { color: var(--bs-danger); font-weight: 600; }

.nlf-res__value { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

.nlf-res__detail,
.nlf-res__rates,
.nlf-res__engines { grid-column: 2 / -1; }

.nlf-res__detail { font-size: .68rem; color: var(--bs-secondary-color); overflow-wrap: anywhere; }

.nlf-res__rates {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-variant-numeric: tabular-nums;
}

/*
 * Zwei Spalten fest. Mit `auto-fit` standen in der Uebersicht drei Engines in
 * einer Zeile und "VideoEnhance" allein darunter, bei 1600 px mit
 * abgeschnittenem Wert (13.09.2026).
 */
.nlf-res__engines {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .2rem .75rem;
}

.nlf-res__engine { display: grid; gap: .1rem; min-width: 0; }
.nlf-res__engine .nlf-res__meter { height: .3rem; }

.nlf-res__engine-head {
    display: flex;
    justify-content: space-between;
    gap: .25rem;
    font-size: .64rem;
    color: var(--bs-secondary-color);
    white-space: nowrap;
    overflow: hidden;
}

.nlf-res__engine-value { font-variant-numeric: tabular-nums; }


/* ============================================================ In Arbeit ==
 *
 * Drei Spalten je Zeile: Art, Gegenstand, Zusatz. Feste erste Spalte, damit
 * die Abzeichen untereinander eine Kante bilden - sonst wandert der Text je
 * nach Wortlaenge ("Cron" gegen "Warteschlange") und die Liste liest sich
 * als Haufen statt als Tabelle.
 */
.nlf-activity {
    display: flex;
    flex-direction: column;
    gap: .45rem;
}

.nlf-activity__row {
    display: grid;
    grid-template-columns: 6.5rem minmax(0, 1fr);
    grid-template-areas: "kind what" ".    more";
    gap: .15rem .6rem;
    align-items: baseline;
}

.nlf-activity__kind {
    grid-area: kind;
    justify-self: start;
    font-weight: 500;
}

.nlf-activity__what {
    grid-area: what;
    font-size: .875rem;
    /* Ein langer Serientitel darf die Karte nicht breiter machen. */
    overflow-wrap: anywhere;
}

.nlf-activity__more {
    grid-area: more;
    font-size: .78rem;
    color: var(--bs-secondary-color);
}

/* Leere Zusatzspalte nimmt keinen Platz weg. */
.nlf-activity__more:empty { display: none; }

/* ============================================ Sortierbare Liste (DLNA-Ansichten)
 *
 * Die Ansichten im DLNA-Bereich lassen sich ziehen; ihre Reihenfolge ist
 * die Reihenfolge auf dem Fernseher. Ohne sichtbaren Griff und ohne
 * Rueckmeldung beim Ziehen merkt niemand, dass es geht.
 */
.nlf-sort__item {
    background: var(--surface-control, transparent);
    cursor: grab;
    transition: opacity .12s ease, border-color .12s ease;
}

.nlf-sort__item:active { cursor: grabbing; }

/* Das gezogene Element bleibt sichtbar, tritt aber zurueck - sonst weiss
 * man beim Loslassen nicht, welches man in der Hand hatte. */
.nlf-sort--active {
    opacity: .45;
    border-color: var(--bs-primary) !important;
}

.nlf-sort__grip {
    cursor: grab;
    font-size: 1.1rem;
    line-height: 1.2;
    user-select: none;
}

/* Die Beschriftung selbst ist NICHT ziehbar - sonst laesst sich der Haken
 * nicht mehr anklicken, ohne dass ein Ziehen beginnt. */
.nlf-sort__item label,
.nlf-sort__item input { cursor: pointer; }

/* =========================================================================
   Bedienung mit dem Finger

   `pointer: coarse` fragt nach dem GERÄT, nicht nach der Fensterbreite. Ein
   schmales Fenster auf dem Schreibtisch bleibt damit unberührt, und ein
   Tablet im Querformat bekommt die grösseren Flächen trotzdem.

   44 Punkte sind kein Geschmack: ein Finger trifft rund 9 mm, und das steht
   so in WCAG 2.5.5 und in Apples Richtlinie. Gemessen am 2.9.2026 lagen im
   Katalog zwölf Bedienelemente darunter - Bootstraps Vorgaben sind 40, 38,
   31 und beim Regler 24.

   Angehoben wird die HÖHE, nicht die Schriftgrösse. Ein Feld, das plötzlich
   grösser schreibt als der Text daneben, sieht kaputt aus; eines, das mehr
   Luft hat, sieht nach nichts aus und lässt sich treffen.
   ========================================================================= */
@media (pointer: coarse) {
    .btn,
    .form-control,
    .form-select,
    .navbar-brand,
    .navbar-toggler,
    .page-link,
    .nav-link,
    .dropdown-item {
        min-height: 44px;
    }

    /* Die Seitenzahlen sind schmal, nicht flach: eine einstellige Zahl war
       27 Punkte breit. Ein Finger trifft quadratisch, nicht hochkant. */
    .page-link {
        min-width: 44px;
    }

    /*
     * Ein <summary> ist ein Knopf, auch wenn es nicht so aussieht. Auf der
     * Titelseite klappt eines die Rohdaten der Dienste auf und war 20
     * Punkte hoch - eine Zeile Text, mehr nicht.
     */
    summary {
        min-height: 44px;
        display: flex;
        align-items: center;
    }

    /* Ein Knopf mit Text braucht die Höhe auch innen, sonst klebt die
       Schrift oben. */
    .btn,
    .navbar-brand,
    .page-link,
    .nav-link {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    .btn-sm {
        /* `btn-sm` ist der kleine Knopf; klein heisst hier schmaler, nicht
           flacher. */
        padding-inline: .75rem;
    }

    /*
     * Der Regler: die Bahn darf schmal bleiben, der Griff nicht. Die Höhe
     * kommt über den Innenabstand, damit die Bahn nicht mitwächst.
     */
    .form-range {
        min-height: 44px;
        padding-block: 10px;
    }
    .form-range::-webkit-slider-thumb { width: 22px; height: 22px; }
    .form-range::-moz-range-thumb     { width: 22px; height: 22px; }

    /*
     * Kacheln im Katalog: der ganze Kasten ist der Griff, nicht nur der
     * Titel. Auf dem Schreibtisch zielt man mit der Maus, mit dem Finger
     * nicht.
     */
    .nlf-card a { display: block; }
}

/* ===========================================================================
   Die Trefferliste der Adminsuche.

   Sie hing zuerst an Bootstraps `dropdown-menu` mit einem Kasten je Zeile.
   Bei acht Treffern standen acht graue Kaesten da, und sie nahmen mehr
   Platz und mehr Aufmerksamkeit als die Namen, um die es geht. Jetzt
   traegt die Gruppe die Beschriftung und die Zeile nur noch Name und
   Hinweis.

   Die Breite haengt NICHT am Eingabefeld. Das ist 14 rem breit, ein
   Dateiname ist es nicht: vorher stand dort "Wenn.Guffman..." und man
   musste raten, welcher Film gemeint ist.
   =========================================================================== */
.nlf-hits {
    position: absolute;
    top: calc(100% + .35rem);
    right: 0;
    z-index: 1080;
    min-width: 30rem;
    max-width: min(46rem, calc(100vw - 2rem));
    max-height: 70vh;
    overflow-y: auto;
    padding: .35rem 0;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    box-shadow: 0 .75rem 2rem rgba(0, 0, 0, .35);
    display: none;
}
.nlf-hits.show { display: block; }

/* Die Gruppenueberschrift: klein, ruhig, einmal je Art. */
.nlf-hits__group {
    padding: .5rem .85rem .2rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.nlf-hits__group:first-child { padding-top: .25rem; }

/*
   Zwei Spalten, nicht zwei Zeilen. Der Name links, der Hinweis rechts und
   gedaempft: so liest man die Liste in einer senkrechten Bewegung.
*/
.nlf-hits__row {
    display: flex;
    align-items: baseline;
    gap: 1rem;
    padding: .4rem .85rem;
    color: var(--bs-body-color);
    text-decoration: none;
}
.nlf-hits__label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.nlf-hits__note {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .8rem;
    color: var(--bs-secondary-color);
}

/*
   Die ausgewaehlte Zeile: ein zarter Grund und ein Strich links, kein
   blauer Block. Der Block schrie die Liste an und machte den Hinweis
   daneben unlesbar.
*/
.nlf-hits__row.is-active,
.nlf-hits__row:hover {
    background: var(--bs-tertiary-bg);
    box-shadow: inset .18rem 0 0 var(--bs-primary);
}

.nlf-hits__empty {
    padding: .6rem .85rem;
    font-size: .85rem;
    color: var(--bs-secondary-color);
}

/* Die Tastenzeile am Fuss: sie erklaert die Bedienung einmal und leise. */
.nlf-hits__foot {
    margin-top: .35rem;
    padding: .45rem .85rem .2rem;
    border-top: 1px solid var(--bs-border-color);
    font-size: .72rem;
    color: var(--bs-secondary-color);
}
.nlf-hits__foot kbd {
    padding: .05rem .3rem;
    font-size: .7rem;
    background: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-radius: .25rem;
}

/* ===========================================================================
   Schmale Bildschirme: nichts darf nach rechts hinauswandern.

   Am 08.09.2026 bei 390 px gemessen. Vier Seiten rollten waagerecht, und
   die Ursachen waren verschieden - deshalb steht hier keine Sammelregel,
   sondern zu jeder eine Zeile mit ihrem Grund.
   =========================================================================== */

/*
   `min-width-0` stand im Markup der Übersicht und gab es NIRGENDS: weder in
   Bootstrap noch hier. Ein Flex-Kind schrumpft von sich aus nicht unter
   seinen Inhalt, also schob die Sparten-Legende die Zeile auf 408 px.
   Eine Klasse, die man schreibt und nicht definiert, wirkt wie ein
   Kommentar: sie sagt, was gemeint war, und tut nichts.
*/
.min-width-0 { min-width: 0; }

/*
 * SICHTPRUEFUNG ALLER SEITEN, 13.09.2026 (bin/qa/layout.mjs und Bilder in 1920
 * und 400 px). Die Regeln hier trafen jeweils mehrere Seiten zugleich.
 *
 * Notizen im Kartenkopf erbten font-weight 600 vom Kopf und standen fett neben
 * dem Titel. Bei 400 px drueckten sie ihn auf zwei bis drei Zeilen oder klebten
 * ohne Abstand daran ("EingangskorbWelche Ordner"). Titel und Notiz duerfen jetzt
 * umbrechen, mit Abstand, die Notiz in normaler Staerke.
 */
.card-header.d-flex {
    flex-wrap: wrap;
    column-gap: .75rem;
    row-gap: .1rem;
}
.card-header > .small,
.card-header > .text-body-secondary {
    font-weight: 400;
}

/*
 * Tabellen direkt in einer Karte, ohne card-body: die erste Spalte begann links
 * vom Titel im Kartenkopf. Erste und letzte Zelle ruecken so weit ein wie der
 * Kopf (.nlf-admin .card-header, .85rem).
 */
.nlf-admin .card > .table-responsive > .table > :not(caption) > * > :first-child {
    padding-left: .85rem;
}
.nlf-admin .card > .table-responsive > .table > :not(caption) > * > :last-child {
    padding-right: .85rem;
}

/* Kopfzellen in Karten einheitlich; manche Tabellen setzten `small`, andere nicht. */
.nlf-admin .card .table > thead th {
    font-size: .8rem;
}

/* Gruppenzeile in einer Tabelle, passend zum Farbschema. `table-light` blieb im dunklen weiss. */
.table > tbody > tr.nlf-group-row > * {
    --bs-table-bg: var(--bs-tertiary-bg);
    --bs-table-color: var(--bs-emphasis-color);
}

/*
 * Kennzahl-Kasten mit Ring: der Textteil wurde nicht schmaler als sein Inhalt
 * und schnitt bei 1280 px ab (/admin/covers, 240 von 245 px).
 */
.nlf-stat.d-flex > .flex-grow-1 {
    min-width: 0;
}

/* Ohne laufenden Job blieb die Karte "Protokoll" leer und sah kaputt aus. */
#nlf-job-log:empty::before {
    content: "Noch keine Ausgabe. Hier erscheint das Protokoll des laufenden Jobs.";
    color: var(--bs-secondary-color);
    font-family: var(--bs-body-font-family);
}

/*
 * Lange Tabellen rollen in ihrer Karte, der Kopf bleibt stehen (Protokoll,
 * Bestand abgleichen). Dasselbe Muster wie .nlf-runs auf /admin/cron.
 */
.nlf-scroll {
    max-height: 70vh;
    overflow-y: auto;
}

/*
 * Vorschau auf /admin/dlna: die Karte ist so hoch wie "Welche Ansichten"
 * daneben, der Baum rollt darin. Vorher streckte h-100 die Karte, und unter
 * wenigen Zeilen blieb die Flaeche leer.
 */
.nlf-dlna-browse {
    position: relative;
    min-height: 16rem;
}
.nlf-dlna-browse > .table-responsive {
    max-height: 28rem;
    overflow-y: auto;
}
@media (min-width: 1200px) {
    .nlf-dlna-browse > .table-responsive {
        position: absolute;
        inset: 0;
        max-height: none;
    }
}

/*
 * Tabellen auf dem Telefon, siehe stackTables() in app.js: jede Zeile ein Block,
 * jede Zelle mit ihrer Spaltenueberschrift davor. Nur Tabellen, die breiter
 * waren als ihr Kasten, tragen die Klasse.
 */
@media (max-width: 575.98px) {
    /* Auch die Tabelle selbst ein Block: als `display: table` wuchs sie auf ihre Textbreite (602 px). */
    table.nlf-stacked {
        display: block;
        min-width: 0 !important;
        table-layout: auto;
    }
    table.nlf-stacked > thead {
        display: none;
    }
    table.nlf-stacked > tbody,
    table.nlf-stacked > tbody > tr,
    table.nlf-stacked > tbody > tr > td,
    table.nlf-stacked > tbody > tr > th {
        display: block;
        width: auto !important;
    }
    table.nlf-stacked > tbody > tr {
        padding-block: .35rem;
        border-bottom: 1px solid var(--bs-border-color);
    }
    table.nlf-stacked > tbody > tr > td,
    table.nlf-stacked > tbody > tr > th {
        border-bottom-width: 0;
        padding: .1rem .85rem;
        text-align: left !important;
        white-space: normal !important;
        overflow-wrap: anywhere;
    }
    table.nlf-stacked > tbody > tr > [data-label]::before {
        content: attr(data-label);
        display: inline-block;
        min-width: 6.5rem;
        margin-right: .5rem;
        font-size: .72rem;
        color: var(--bs-secondary-color);
    }
}

/*
 * Gruppen auf /admin/covers: jede Gruppe ein Block aus Kopf und Karten, mehrere
 * Gruppen nebeneinander. Die Karten behalten ihre Breite von 23rem.
 */
/*
 * Ein Raster mit Spalten fuer zwei Karten (2 x 23rem und Abstand): mit einem
 * umbrechenden Flex-Block rechnete der Browser die Gruppe aus der Inhaltsbreite
 * ihrer Karten und machte sie 1.202 px breit, jede stand wieder allein.
 */
.nlf-covers:has(> .nlf-covers__set) {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(47.5rem, 100%), 1fr));
    align-items: start;
    column-gap: 1.5rem;
    row-gap: 1rem;
}
.nlf-covers__set {
    display: flex;
    flex-wrap: wrap;
    gap: .8rem;
    min-width: 0;
    padding-top: .5rem;
    border-top: 1px solid var(--bs-border-color);
}
.nlf-covers__set > .nlf-covers__group {
    flex: 1 0 100%;
    border-top: 0;
    padding: 0;
}
/*
 * Feste Grundbreite 23rem: mit `min(23rem, 100%)` rechnete der Block mit der
 * Inhaltsbreite der Karten und wurde bei zwei Karten 1.556 px breit, jede Gruppe
 * stand wieder allein. min-width 0 und max-width 100%: bei 400 px wurde eine Karte
 * sonst nicht schmaler als ihr Inhalt (505 px).
 */
.nlf-covers__set > .nlf-cover {
    flex: 0 1 23rem;
    max-width: 100%;
    min-width: 0;
}

/*
 * Eine Zeitreihe (Chart::columns mit .nlf-chart--timeline) darf ab 768 px
 * schmaler werden als ihre 1.200 Einheiten, sie teilt sich auf /admin/logs die
 * Zeile mit dem Filter. Darunter rollt sie und beginnt rechts (app.js).
 */
@media (min-width: 768px) {
    /* Doppelte Klasse: `.nlf-chart-roll > .nlf-chart` steht weiter unten und gewann sonst. */
    .nlf-chart-roll > .nlf-chart.nlf-chart--timeline {
        min-width: 0;
    }
}

/* Zweizeilige Etiketten in Tabellen stiessen mit Bootstraps Zeilenhoehe 1 aneinander. */
.nlf-badge-wrap {
    line-height: 1.25;
    padding-block: .3em;
}

/*
 * Die Mindestquote im Katalog sass 7 px tiefer: der Schieber ist niedriger als ein
 * Auswahlfeld, und die Leiste richtete unten aus. Oben ausgerichtet stehen alle
 * Beschriftungen auf einer Linie, und die Zeile wird nicht hoeher.
 */
.nlf-filter-bar {
    align-items: start;
}

@media (max-width: 575.98px) {
    /* Katalog am Telefon: die Suche bleibt offen, die uebrigen Filter stehen hinter "Filter". */
    .nlf-filter-bar:not(.nlf-filter-bar--open) > :not(.nlf-filter-bar__wide) {
        display: none;
    }
}
.nlf-scroll > .table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 1;
    background-color: var(--bs-card-bg, var(--bs-body-bg));
    box-shadow: inset 0 -1px 0 var(--bs-border-color);
}

@media (max-width: 575.98px) {
    /*
     * Kennzahlen zweispaltig. Mit minmax(13rem) stand bei 400 px jede allein,
     * und vier Kaesten reichten auf /admin/covers bis 660 px herunter.
     */
    .nlf-stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: .5rem;
    }
    .nlf-stat {
        padding: .6rem .7rem .55rem;
    }
    /* 1,35rem schnitt "11.347.863" auf /admin/jobs ab (160 von 202 px). */
    .nlf-stat__value {
        font-size: 1.2rem;
    }
    /* Die Sammelknoepfe auf /admin/issues brechen als Ganzes um; nebeneinander waren sie 421 px breit. */
    .nlf-batch__group {
        display: flex;
        flex-wrap: wrap;
    }
    /* Die Beschriftung eines Balkens nimmt hoechstens 40 %; mit label_width 210 blieb fuer ihn fast nichts. */
    .nlf-bars__row {
        grid-template-columns: minmax(0, min(var(--bar-label, 150px), 40%)) minmax(2rem, 1fr) var(--bar-value, 78px);
    }
    /* Die Sparkline lag absolut ueber der Notiz ("Rechenzeit" auf /admin/cron). */
    .nlf-stat__spark {
        position: static;
        display: block;
        width: 100%;
        margin-top: .3rem;
    }
    /* Begriffe in schmalen dt-Spalten trennen, statt sie mitten im Wort zu brechen. */
    dl.row > dt {
        hyphens: auto;
        overflow-wrap: break-word;
    }
}

@media (max-width: 575.98px) {
    /*
       Der Abschnittskopf ist eine Flex-Zeile aus Titel, Linie und Notiz.
       Bei 390 px blieben dem Titel 60 px, und "Was gerade läuft" stand
       dreizeilig übereinander. Auf schmalen Schirmen bricht die Zeile
       stattdessen um.
    */
    .nlf-section {
        flex-wrap: wrap;
    }
    .nlf-section__title {
        flex: 0 0 100%;
    }
    .nlf-section__line {
        display: none;
    }

    /*
       Bis zum 13.09.2026 standen die Kennzahlkästen am Telefon untereinander,
       und ihr Wert war hier 2rem gross. Seit sie zweispaltig stehen, gilt die
       kleinere Schrift aus dem Block "Sichtpruefung aller Seiten" weiter oben;
       2rem schnitt dort "11.347.863" ab.
    */
}

@media (max-width: 575.98px) {
    /*
       Die runden Diagramme dürfen am Telefon die Breite nutzen.

       `Chart::open()` setzt `width="100%"` und eine FESTE Höhe. Bei
       `preserveAspectRatio="xMidYMid meet"` begrenzt damit die Höhe den
       Kreis, gleich wieviel Platz daneben frei ist: am 08.09.2026 bei
       390 px gemessen war der Sparten-Ring 150 Punkte gross, in einem
       Kasten von 330. Eine Höhe in `vw` lässt ihn mitwachsen.

       Das Seitenverhältnis und nicht eine Höhe in `vw`: ein erster Versuch
       mit `min(52vw, 220px)` machte den Ring auf der Übersicht richtig
       gross und blies ihn auf der Befundseite auf 136 mal 203 auf, weil
       sein Kasten dort schmal ist. `aspect-ratio: 1` lässt die Höhe der
       Breite folgen, gleich welcher.

       Der Deckel bei 220 px verhindert das Gegenteil: ein Ring, der ein
       halbes Bildschirmfenster füllt, verdrängt die Zahlen, um derentwillen
       man die Seite öffnet.
    */
    .nlf-chart--donut {
        height: auto;
        aspect-ratio: 1;
        max-height: 220px;
    }

    /*
       Die Sparten-Karte stellt Ring und Legende nebeneinander. Bei 390 px
       bleiben der Legende dann 200 Punkte, und jeder Name bricht um.
       Untereinander bekommen beide die volle Breite.

       Der Platz des Diagramms traegt dafuer die Klasse `nlf-chart-slot`.
       Vorher stand hier ein Selektor auf das Attribut `style`, und der
       traf nur die Uebersicht: die Befundseite setzt 8,5 rem statt 9,5.
       Eine Regel, die an einer Zahl im Markup haengt, findet die naechste
       Karte nicht.
    */
    .card-body.d-flex.align-items-center.gap-3 {
        flex-wrap: wrap;
    }
    .nlf-chart-slot {
        width: 100% !important;
    }
}

/* ── Diagramme am schmalen Schirm ───────────────────────────────────────────
   GEMESSEN am 9.9.2026 auf einem Samsung S8 (360 px):

       Befunde nach Art   viewBox 820   auf 302 px   Skala 0.37   5,0 px Schrift
       Jahrgaenge         viewBox 1400  auf 302 px   Skala 0.22   3,0 px Schrift

   Der `viewBox` steht auf Schreibtischbreite, und beim Verkleinern schrumpft
   die Beschriftung mit. `Chart::open()` gibt die Breite deshalb als
   `--chart-w` mit; hier wird daraus eine Mindestbreite, und der Kasten
   darum rollt.

   Warum rollen und nicht kleiner zeichnen: eine Zeichnung, die in 360 px
   passt, hat fuer 20 Balken mit Beschriftung keinen Platz. Breite Tabellen
   loesen dasselbe Problem im Baum schon so, und die Seite selbst bleibt
   dabei stehen.
   ────────────────────────────────────────────────────────────────────────── */
/*
   OHNE MEDIENABFRAGE, und das ist Absicht.

   Der erste Versuch band die Regel an `max-width: 900px`. Am Schreibtisch
   stand das Balkendiagramm dann weiter in einer 547 px schmalen Spalte und
   zeichnete seine Beschriftung mit 9,0 px. Es geht nicht um die Breite des
   Schirms, sondern um das Verhaeltnis von Zeichnung zu Platz: `width="100%"`
   fuellt den Kasten, sobald er breit genug ist, und die Mindestbreite greift
   nur, wenn er es nicht ist.
*/
.nlf-chart-roll {
    overflow-x: auto;
    overflow-y: hidden;
    /* Damit der Rollbalken nicht auf der Zeichnung klebt. */
    padding-bottom: .25rem;
    -webkit-overflow-scrolling: touch;
}

/*
   Nur Diagramme, die breiter als der Platz sind. Ein Ring von 152
   Einheiten soll weiter mitwachsen und keine Mindestbreite bekommen.
*/
.nlf-chart-roll > .nlf-chart {
    min-width: calc(var(--chart-w, 320) * 1px);
    height: calc(var(--chart-h, 160) * 1px);
}

/* Der Ring bleibt rund und passt sich an, er hat keine Beschriftung. */
.nlf-chart-roll > .nlf-chart--donut,
.nlf-chart--donut {
    min-width: 0;
    height: auto;
}

/*
 * Streifen und Verlauf ebenfalls: ohne Schrift gibt es nichts, das beim
 * Schrumpfen unlesbar wuerde. `Chart::open()` dehnt sie mit
 * preserveAspectRatio="none". Bis zum 13.09.2026 rollten "Sparten" auf /admin
 * und "Wo die Arbeit liegt" auf /admin/issues bei jeder Breite waagerecht.
 */
.nlf-chart-roll > .nlf-chart--stack,
.nlf-chart-roll > .nlf-chart--spark {
    min-width: 0;
}

/* ── Kopfleiste des Adminbereichs bricht um ─────────────────────────────────
   GEMESSEN am 9.9.2026: bei 1440 px lief die Seite um 123 px waagerecht
   ueber, bei 1280 px um 57. Der Platz nach der Marke betraegt 1191 px, die
   Leiste braucht 1314: das Menue links 470, die Gruppe rechts 845.

   Der Kommentar im Markup nennt denselben Fall mit 7 bis 13 px bei 1280.
   Seither sind Eintraege dazugekommen, und aus einem Rundungsfehler wurde
   eine handbreite Verschiebung der ganzen Seite.

   `flex-wrap` statt Schrumpfen: das Suchfeld auf 8 rem zu quetschen macht es
   unbrauchbar, und ein Menuepunkt mit abgeschnittenem Wort ist kein Menue.
   Eine zweite Zeile kostet 38 px Hoehe und keine Lesbarkeit.
   ────────────────────────────────────────────────────────────────────────── */
.navbar .navbar-collapse {
    flex-wrap: wrap;
    row-gap: .5rem;
}

/*
   Damit die rechte Gruppe als Ganzes umbricht und nicht in ihre Teile
   zerfaellt: Suchfeld, Kennzeichen und Knopf gehoeren zusammen.
*/
.navbar .navbar-collapse > .d-flex {
    flex-wrap: nowrap;
}

/* ── Die Kopfleiste passt in eine Zeile ─────────────────────────────────────
   GEMESSEN am 9.9.2026 bei 1440 px: Marke 222, Menue 468, Gruppe rechts 853,
   zusammen 1543 auf 1440 Punkten Platz. Zwei Teile waren unnoetig breit:

       Suchfeld            224 px   (feste `width:14rem` im Markup)
       Auftragsanzeige     206 px   (steht nur da, wenn ein Job laeuft)
       Lastanzeige         210 px   (ab 1400 px sichtbar)

   Mit 12 rem fuer die Auftragsanzeige blieben bei 1440 px noch 33 px zuviel,
   deshalb 9 rem. Gemessen, nicht geschaetzt.

   Beide bekommen jetzt eine Obergrenze statt einer festen Zahl. Das Suchfeld
   waechst mit dem Fenster und wird nie schmaler als 9 rem; darunter ist es
   kein Suchfeld mehr. Die Auftragsanzeige kuerzt ihren Text mit Auslassung:
   ihr Zweck ist "da laeuft etwas", die Einzelheiten stehen auf /admin/jobs.
   ────────────────────────────────────────────────────────────────────────── */
#nlf-search {
    width: clamp(9rem, 14vw, 14rem);
}

#nlf-job-badge {
    max-width: 9rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

#nlf-load {
    max-width: 9rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Seit 11.09.2026 ein Link zur Uebersicht: beim Zeigen unterstreichen. */
#nlf-load:hover,
#nlf-load:focus-visible {
    text-decoration: underline !important;
}

/*
   Ein Auswahlfeld mit `width:auto` ist so breit wie seine laengste Zeile.
   Auf /admin/covers heisst die laengste "alle Cover vom Dienst uebernehmen
   (306)" und misst 359 px; auf einem 360-px-Schirm lief die Seite dadurch um
   28 px ueber (gemessen am 9.9.2026). Die Obergrenze kostet nichts: passt es,
   aendert sich nichts, passt es nicht, bricht der Text um.
*/
.form-select,
.form-control {
    max-width: 100%;
}

/* ------------------------------------------------------ Metadaten-Anbieter */
/*
 * Die Beschreibung eines Anbieters brach auf drei bis vier Zeilen um und
 * machte jede Tabellenzeile so hoch. Zwei Zeilen reichen, den vollen Text
 * zeigt das `title`-Attribut.
 */
.nlf-prov__note {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    max-width: 32rem;
}

.nlf-meta > tbody > tr > td {
    padding-top: .65rem;
    padding-bottom: .65rem;
}

/* =========================================================================
   Footer mit den Quellenhinweisen der Anbieter, siehe app/Attribution.php

   M. Martin am 12.09.2026: die Hinweise hintereinander statt untereinander,
   Schrift kleiner, Trennzeichen dazwischen. Der Strich kommt aus dem CSS und
   nicht aus dem HTML, damit `bin/qa/attribution.php` die Pflichtsätze im
   Wortlaut findet: `strip_tags` liest erzeugte Inhalte nicht mit.

   Die Verweise stehen mitten im Satz und sind eine Zeile hoch, 15 Punkte.
   Gemessen am 11.09.2026 mit bin/qa/touch.mjs: 10 Verweise lagen unter 44.
   Mit dem Finger bekommt jede Zeile deshalb 44 Punkte Höhe, und der Verweis
   füllt sie. Der erste Versuch gab nur den Verweisen die Höhe: die Zeilen mit
   Verweis standen dann weiter auseinander als die ohne.

   Gemessen am 12.09.2026: mit der Maus auf 1280 px stehen die sieben Hinweise
   in zwei Zeilen, der Footer ist 87 px hoch. Mit dem Finger auf 390 px sind es
   429 px, kleinster Verweis 44 Punkte. Untereinander wären es dort 517 px.
   ========================================================================= */
/*
 * Footer am Boden (14.09.2026). M. Martin: „Bitten den Footer immer am Boden fixieren falls Content
 * nicht hoch genug bzw. beim scrollen am Ende der Seite. Also nicht fixed oder static, etc.
 * verwendet.“ Die Seite ist eine Spalte ueber mindestens die Fensterhoehe, der Hauptteil waechst:
 * bei kurzem Inhalt steht der Footer unten im Fenster, bei langem am Ende der Seite.
 */
.nlf-app {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
}
.nlf-app > main {
    flex: 1 0 auto;
}
/* Die Abspielleiste der Audioseite liegt fest unten; solange sie steht, bleibt der Footer darueber. */
.nlf-app:has(#nlf-audio-player:not([hidden])) {
    padding-bottom: 4.5rem;
}

.nlf-footer {
    font-size: .75rem;
}

.nlf-footer li {
    display: inline;
}

.nlf-footer li + li::before {
    content: "|";
    margin: 0 .5em;
    opacity: .55;
}

@media (pointer: coarse) {
    .nlf-footer ul {
        line-height: 44px;
    }
    .nlf-footer a {
        display: inline-block;
        min-width: 44px;
    }
}
