/* Farbpalette und Maße der Oberfläche ------------------------------------------------------------
 *
 * Zentral definiert, weil dieselben Werte sonst über das ganze Stylesheet verstreut wären (vor der
 * Vereinheitlichung stand allein die alte Grundfarbe an 47 Stellen). Wer die Optik nachjustieren will,
 * ändert hier eine Zeile statt dutzender.
 *
 * Die Formensprache stammt aus dem TMDB-Bereich und gilt seitdem für die ganze Anwendung: Bedienelemente mit
 * Beschriftung sind Pillen, reine Icon-Schaltflächen sind Kreise, beide gleich hoch (--control-height). */
:root {
	/* Bedienelemente (Schaltflächen, Menüs, Formularelemente) */
	--control-bg:              #1b2b52;
	--control-border:          #4a70b0;
	--control-text:            #cfe0f5;
	/* Die "hover"-Stufe trägt den Namen nur noch aus historischen Gründen: Sie steht inzwischen für "hervorgehoben"
	   und wird von .active (gewähltes Segment, offene Filterleiste) und von :active (gedrückt) genutzt. Echte
	   Hover-Effekte gibt es außer beim Tooltip keine mehr - warum, steht bei [data-tooltip]. */
	--control-bg-hover:        #2a4383;
	--control-border-hover:    #7aa0e0;
	--control-text-hover:      #fff;
	--control-bg-disabled:     #16203a;
	--control-border-disabled: #2a3a5a;
	--control-text-disabled:   #667;
	--control-height:           2rem;
	--control-height-small:     1.6rem; /* kompakte Variante für dichte Zeilen, siehe .miniBtn */
	--control-radius:           999px;
	/* Eingabe- und Auswahlfelder sind bewusst nur abgerundet statt voll rund: in einer Pille liefe der Text in die
	   runden Enden, was bei langen Eingaben (Suche, Pfade, Textbereiche) schlecht zu lesen ist. Die Höhe teilen sie
	   sich dagegen mit den Schaltflächen, damit gemischte Zeilen fluchten. */
	--field-radius:             8px;

	/* Flächen */
	/* Seitenhintergrund. Wie --surface auf dem Blauton der Bedienelemente (223°), nur dunkler und schwächer
	   gesättigt: das alte #003 lag bei 240° und voller Sättigung und stach damit aus der Familie heraus - die
	   entsättigten Kacheln und Karten darauf wirkten grau statt zugehörig. */
	--page-bg:        #0d1426;
	/* Karten, Kacheln und Formulare. Die Helligkeit ist bewusst deutlich unter der von --control-bg: bei
	   annähernd gleicher Helligkeit (vorher 20% gegen 21%) heben sich Felder und Schaltflächen darauf nur noch
	   durch ihren Rahmen ab, das Formular wirkt flach und die Elemente aufgeklebt. So entsteht eine Staffelung
	   Seite (10%) - Fläche (15%) - Bedienelement (21%). Der Farbton folgt dem der Bedienelemente (223°); vorher
	   lag er bei 240° und damit sichtbar in einer anderen Farbfamilie. */
	--surface:        #172036;
	--surface-raised: #1b2b52; /* Aufliegendes ohne eigene Bedienelemente: Menüs */
	/* Dialoge liegen dunkler als die Bedienelemente darin - dieselbe Beziehung wie auf der Seite, wo Felder und
	   Schaltflächen ebenfalls heller als ihr Untergrund sind. Ein heller Dialogkörper wäre bei großen Dialogen
	   (Trefferliste, Tabelle) eine grelle Fläche mit zu wenig Kontrast zum Inhalt. Etwas heller als die Seite
	   bleibt er trotzdem, damit er sich als aufliegend abhebt. */
	--surface-dialog: #111d3d;

	/* Linien und große Flächen sind bewusst deutlich weniger gesättigt als die Bedienelemente: derselbe kräftige
	   Blauton, der einen 2rem großen Button trägt, wirkt über eine ganze Seitenkante oder einen Tabellenkopf
	   gezogen grell. Die kleinen Elemente behalten ihn (--control-border, 41% Sättigung), die Struktur liegt bei
	   rund 21% - dem Niveau, das die Anwendung vor der Vereinheitlichung hatte.
	   --line trägt die sichtbare Struktur (Seitenkopf, Seitenleiste, Trenner), --line-subtle die Andeutung einer
	   Kante innerhalb einer Fläche (Kachelrahmen). */
	--line:        #5f6e91;
	--line-subtle: rgba(102,153,221,0.25);
	/* Tabellen bekommen eine neutrale Linie statt einer blauen: eine Aufnahme- oder EPG-Liste besteht aus sehr
	   vielen Linien, in der Bereichsfarbe würde die Seite blaustichig. */
	--line-table:  #999;
	/* Band für dauerhaft sichtbare Flächen: Dialog-Kopfzeile, Akkordeon-Köpfe. Bewusst nicht --control-bg-hover,
	   obwohl das farblich naheläge: dieser Ton ist für kleine, kurz sichtbare Zustände gedacht (ein Element unter
	   dem Mauszeiger, ein gewähltes Segment). Über ein breites, dauerhaft stehendes Band gezogen wirkt seine hohe
	   Sättigung laut - im Textfilter-Dialog stapeln sich gleich mehrere davon. */
	--surface-band: #424c67;

	/* Band des Tabellenkopfs, samt Schriftfarbe darauf: dieselbe Fläche wie die Bedienelemente, damit der Kopf
	   nicht als dritter Farbton neben Fläche und Schaltflächen steht. Die Schrift ist bewusst fast weiß und nicht
	   --control-text, das hellblau ist und dem Kopf einen Blaustich gab. */
	--table-header-bg:   #1b2b52;
	--table-header-text: #f2f2f2;

	/* Text */
	--text:        #ddd;
	--text-muted:  #aaa;
	/* Nur für Zeichen, die zurücktreten sollen, statt gelesen zu werden: Platzhalter-Symbole auf leeren Postern
	   und Folgenbildern, ausgegraute Blätterpfeile. Bewusst kein Grau, sondern der Blauton der Familie (223°). */
	--text-faint:  #555e77;

	/* Bedeutungsfarben - sie tragen eine Aussage und folgen deshalb nicht der Bereichsfarbe:
	   blau "gesammelt", grün "gesehen", lila "Filmreihe", gelb "Bewertung". */
	--accent-collected:  #6af;
	--accent-watched:    #6c6;
	--accent-collection: #cae;
	--accent-rating:     #fc6;
	/* Rot für die Merkliste des Streaming-Portals - das Herz kennt man von anderen Diensten in genau dieser Farbe,
	   und keine der vier darüber ist noch frei (siehe inc/tmdbMeta.html#watchlistHeart). */
	--accent-watchlist:  #e5566b;

	/* Bereichsgruppen. Dieselbe Einteilung trägt die Startseite (Beschriftungsbalken der Gruppenkacheln) und die
	   Seitenleiste (Streifen an der Gruppenkante), damit ein Bereich überall dieselbe Farbe hat. Bewusst gedeckt
	   und nur als schmaler Streifen eingesetzt: über größere Flächen gezogen würde die Anwendung bunt. */
	--group-recording: #46698a;
	--group-mediathek: #4a7a5f;
	--group-misc:      #6b6350;
	/* Aufgehellte Fassungen für den aktiven Eintrag im Flyout (Variante B): derselbe Farbton, nur deutlich heller,
	   damit die Gruppe erkennbar bleibt und die Markierung trotzdem heraussticht. */
	--group-recording-bright: #7aa9d8;
	--group-mediathek-bright: #74bd93;
	--group-misc-bright:      #b8a87e;

	/* Karteireiter auf der Startseite: die Bereichsmarke (siehe .homeRowsLabel) und die Überschrift jeder Reihe
	   (siehe .homeCardRows h3). Gleiche Form, unterschiedliche Farbe - allein daran hängt die Rangfolge, denn
	   nebeneinandergestellt sähen zwei graue Reiter gleichrangig aus. Der Bereich trägt deshalb das Grün seiner
	   Gruppe, die Reihen darunter das neutrale Grau der Trenner. */
	--home-label-color:     var(--group-mediathek);
	--home-row-label-color: var(--line);

	/* Markierung der TEST-Instanz im Logo (siehe .testTag): bewusst ein Farbton, der in keiner der Gruppen- oder
	   Bedeutungsfarben oben vorkommt, damit er nicht mit einer von ihnen verwechselt wird. */
	--test-tag-color: #f0a030;
}

html {
	box-sizing: border-box;
}

/* Inherit box-sizing */
*, *::before, *::after {
	box-sizing: inherit;
}

body {
	background: var(--page-bg);
	color: #ddd;
	font-family: Verdana, sans-serif;
	margin: 0;
}

a {
	color: #fff;
	text-decoration: none;
}

/* Header --------------------------------------------------------------------------------------- */

header {
	align-items: center;
	background: linear-gradient(180deg, var(--page-bg), var(--surface));
	border-bottom: 1px solid var(--line);
	display: flex;
	gap: 1rem;
	height: 4rem;
	padding: 0;
	position: fixed;
	top: 0;
	width: 100%;
	z-index: 10;
}

.menuBtn {
	align-items: center;
	background: transparent;
	border: none;
	border-right: 1px solid var(--line);
	color: #aaa;
	cursor: pointer;
	display: flex;
	flex-direction: column;
	flex-shrink: 0;
	font-size: 1.5rem;
	height: 4rem;
	justify-content: center;
	margin: 0;
	padding: 0;
	transition: width 0.3s ease;
	width: 5.5rem;
}

.menuBtn:active {
	color: #fff;
}

.menuBtn .label {
	font-size: 0.7rem;
	margin-top: 0.2em;
}

h1 {
	font-size: 2em;
	margin: 0;
	width: fit-content;
}

.logo {
	display: block;
	font-size: 1rem; /* Anker für .testTag, das relativ dazu (em) skaliert - siehe dort */
	height: 3rem;
	margin: 0;
	position: relative; /* Anker für .testTag */
}

.logo img {
	height: 100%;
}

/* Kennzeichnet die TEST-Instanz (siehe testInstance im Template-Kontext, TemplateEngine.evaluate) direkt im Logo,
   damit auf Tablet/Handy sofort erkennbar ist, in welcher der beiden Instanzen man sich befindet. Bewusst außerhalb
   des Flex-Flusses der Kopfzeile (position: absolute statt eines echten Flex-Kindes): .globalActions ist auf
   schmalen Viewports bereits sehr eng bemessen (siehe dortige Regeln unter max-width: 640px), ein zusätzliches
   Element im normalen Fluss würde ihr dort Platz wegnehmen. em-Größe statt rem, damit das Tag automatisch mit
   .logo (und dessen eigenem font-size) mitschrumpft, ohne eine eigene Media-Query zu brauchen. pointer-events: none,
   damit das Tag den Klick auf das Logo (Link zur Startseite) an keiner Stelle blockiert.
   Verankert ist es an oben/rechts, nicht an unten/links: so wächst es bei einer Änderung der Schriftgröße nach
   unten und nach links ins Wort hinein, statt oben aus der Kopfzeile herauszulaufen. */
.testTag {
	background: var(--test-tag-color);
	border-radius: var(--control-radius);
	color: #1b1204;
	display: inline-block;
	font-size: 0.78em;
	font-weight: bold;
	letter-spacing: 0.03em;
	line-height: 1;
	padding: 0.15em 0.5em;
	pointer-events: none;
	position: absolute;
	right: 0.2em;
	top: -0.15em;
	white-space: nowrap;
}

/* "TEST" steht in Großbuchstaben und hat damit keine Unterlängen - die Zeilenbox reserviert darunter trotzdem
   Platz dafür, weshalb die Schrift in der Pille sichtbar zu hoch sitzt (gemessen 1,88px bei 12,89px Pillenhöhe).
   align-items: center hilft dagegen nicht: zentriert wird die Zeilenbox, und die enthält den leeren Raum bereits.
   text-box-trim schneidet die Box stattdessen auf Versalhöhe bis Grundlinie zu, sodass das symmetrische Padding
   die tatsächlichen Buchstaben zentriert (gemessen 0,13px Restabweichung). Weil dabei rein geometrisch nach den
   Schriftmetriken geschnitten wird, gilt das für jede Schrift - wichtig, weil Verdana nicht überall vorhanden ist
   und der Ersatz andere Metriken mitbringt.
   Das größere Padding gleicht die weggeschnittene Höhe wieder aus, damit die Pille gleich groß bleibt; beides
   steht deshalb zusammen im @supports und nicht in der Regel oben - Browser ohne text-box-trim bekämen sonst eine
   zu hohe Pille. */
@supports (text-box-trim: trim-both) {
	.testTag {
		padding: 0.28em 0.5em;
		text-box: trim-both cap alphabetic;
	}
}

/* Die Gruppe spannt den freien Bereich zwischen Logo und rechtem Rand auf, damit der "Jetzt läuft"-Kasten ihn
   breit ausfüllen kann. Die Rechtsbündigkeit kommt deshalb aus justify-content und nicht mehr aus margin-left:auto:
   sie hängt so an einer Eigenschaft des immer vorhandenen Containers statt an einer Auto-Margin eines Kindes, das
   es nur gibt, wenn gerade etwas läuft. Sonst säßen die festen Schaltflächen je nach Wiedergabezustand woanders. */
.globalActions {
	align-items: center;
	display: flex;
	flex: 1 1 auto;
	gap: 0.5em;
	height: 100%;
	justify-content: flex-end;
	min-width: 0;
	padding-right: 1em;
}

/* Alle Symbole der Kopfzeile gleich groß. Die beiden Flyout-Auslöser müssen ausdrücklich mit aufgeführt werden:
   sie sind .iconBtn und keine .rcBtn, und ihre eigenen Regeln setzen "font-size: inherit", damit sie sich ihrem
   jeweiligen Einsatzort anpassen - hier ist dieser Einsatzort genau diese Regel. */
.globalActions .rcPower,
.globalActions .rcMute,
.globalActions .nowPlayingToggle,
.globalActions .toggleRemote,
.globalActions .gotoRemote {
	font-size: 2.5em;
}

/* Die aktive Box ist im Standby (siehe base.html) - rein farblicher Hinweis, sonst bleiben die Knöpfe unverändert
   bedienbar (z.B. um die Box per rcPower wieder aufzuwecken). */
.globalActions.boxInStandby .rcPower,
.globalActions.boxInStandby .rcMute,
.globalActions.boxInStandby .toggleRemote {
	color: var(--text-faint);
}

/* Ohne Flex sitzen die Glyphen rund 4px zu hoch in ihren Schaltflächen: die Zeilenbox reserviert unter der Glyphe
   Platz für Unterlängen, den ein Symbol nicht braucht. Die Schaltflächen selbst stehen dabei mittig - nur ihr
   Inhalt nicht. Gleiches Vorgehen wie bei .infoBar .iconBtn.
   Die Regel muss VOR den display-Regeln der beiden Fernbedienungs-Schaltflächen stehen: sie hat dieselbe
   Spezifität wie diese, und bei Gleichstand gewinnt die spätere - andernfalls hebt sie deren "display: none" auf
   und das Symbol erscheint doppelt. */
.globalActions .iconBtn {
	align-items: center;
	display: inline-flex;
	justify-content: center;
}

.globalActions .gotoRemote {
	display: none;
}

.globalActions .toggleRemote.active,
.globalActions .gotoRemote.active {
	color: #6af;
}

/* "Jetzt läuft" in der Kopfzeile ---------------------------------------------------------------- */

/* Ein Markup, zwei Darstellungen (siehe inc/nowPlaying.html): Grundzustand ist das gewöhnliche Flyout unter einem
   Symbol - dafür ist hier nichts zu tun, das erledigen die .actions .moreFlyout-Regeln weiter unten. Ab 1025px
   (Block am Ende dieses Abschnitts) wird derselbe Kasten zum statischen Inline-Element.
   Die Umschaltbreite ist 1025px und nicht 640px, weil zwischen 641 und ~850px nur 36 bis 195px frei bleiben - für
   zwei Textzeilen zu wenig. Ab 1025px sind es mindestens 420px.
   Die Überschreibungen unten stehen VOR den .actions-Regeln, deshalb reicht Quellreihenfolge nicht: sie brauchen
   durchweg höhere Spezifität, daher die Form .moreFlyout.nowPlayingFlyout (zwei Klassen am selben Element). */

/* Der Wrapper wird kopfzeilenhoch, damit das top:100% des Menüs an deren Unterkante sitzt und nicht mitten im
   Header. Bewusst nur der direkte Kindpfad: das Tonspur-Menü liegt inzwischen *innerhalb* dieses Menüs und soll
   seinen eigenen inline-block aus .audioTrackActions .actionWrapper behalten. */
.globalActions > .actions > .actionWrapper {
	align-items: center;
	display: flex;
	height: 100%;
}

/* Blau wie der Titel im aufgeklappten Kasten - das Symbol vertritt ihn ja auf schmalen Bildschirmen. Mit
   .globalActions davor, weil ".iconBtn { color: white }" bei gleicher Spezifität weiter unten in der Datei steht.
   Durchweg .nowPlayingToggle statt ".nowPlayingActions .toggleMoreFlyout": seit der Tonspur-Auslöser innerhalb
   dieses Kastens liegt, träfe die zweite Form ihn mit und machte ihn 2.5em groß und blau. */
.globalActions .nowPlayingToggle {
	color: #6af;
}

/* Ohne die feste Schriftgröße erben beide Flyouts unter 640px die 0.6em der Buttongruppe (siehe Media Query) und
   wären rund 9px groß - der Inhalt hat mit der Größe der Symbole nichts zu tun. */
/* margin-top größer als die 2px von ".actions .moreFlyout": in der Kopfzeile stehen die Menüs unter großen
   Symbolen, und mit dem knappen Abstand kleben sie an ihnen. Gilt auch für das Tonspur-Menü, das im "Jetzt
   läuft"-Menü steckt.
   ".actions" muss mit in den Selektor, sonst herrscht Gleichstand mit ".actions .moreFlyout" und die gewinnt über
   die Quellreihenfolge - font-size und max-width blieben davon zwar unberührt (die setzt sie nicht), margin-top
   aber nicht. */
.globalActions .actions .moreFlyout {
	font-size: 1rem;
	margin-top: 8px;
	max-width: min(80vw, 28rem);
}

.nowPlayingActions {
	min-width: 0;
}

/* Läuft nichts, bleibt das Element als leere Hülle stehen: nowPlaying.js braucht einen festen Platz zum Austauschen und
   einen Träger für data-version. Sichtbar sein darf es dabei nicht, sonst entstünde in .globalActions eine Lücke. */
.nowPlayingActions.nowPlayingEmpty {
	display: none;
}

.nowPlayingToggle {
	padding: 0 5px;
}

/* Wie beim Tonspur-Auslöser: die 1.2rem aus ".actions button i" würden das Symbol kleiner machen als seine
   Nachbarn, es soll aber die 2.5em der Buttongruppe übernehmen. ".globalActions" davor ist nötig, weil
   ".actions button i" mit (0,1,2) sonst die höhere Spezifität hätte. */
.globalActions .nowPlayingToggle i {
	font-size: inherit;
}

/* Gefüllt nur, solange das Menü offen ist, sonst die schlankere Bold-Variante (siehe die beiden Symbole in
   inc/nowPlaying.html). Der Kindselektor im :has() ist wichtig: im "Jetzt läuft"-Menü steckt das Tonspur-Menü,
   und ohne ihn bliebe das Symbol auch dann gefüllt, wenn nur noch jenes offen wäre. */
.nowPlayingIconOpen {
	display: none;
}

.actionWrapper:has(> .moreFlyout.open) .nowPlayingIconIdle {
	display: none;
}

.actionWrapper:has(> .moreFlyout.open) .nowPlayingIconOpen {
	display: block;
}

/* Im aufgeklappten Zustand (schmaler Bildschirm) bleibt es bei der Spalte aus ".actions .moreFlyout": die
   Schaltflächen stehen unter den Textzeilen, damit denen die volle Breite des Kastens bleibt. Nebeneinander
   stehen sie erst im Inline-Zustand, wo die Höhe knapp und die Breite reichlich ist (siehe unten). */
.actions .moreFlyout.nowPlayingFlyout {
	gap: 0.5em;
}

/* Titel-Link und Schaltflächen bekämen sonst das Aussehen von Menüeinträgen aus ".actions .moreFlyout button,
   .actions .moreFlyout a" (Flex über die volle Breite mit Innenabstand). Beim Titel verhinderte das zusätzlich die
   Ellipsis, weil das Element nie schmaler als sein Text würde; bei den Schaltflächen sind display:flex und
   width:100% block-artig und stellten Wiedergabe und Stopp untereinander statt nebeneinander. */
/* color muss mit hier hinein: ".actions .moreFlyout a" setzt weiß und schlüge ein #6af an .nowPlayingTitle
   (0,1,0) sonst. Blau wie in der Info-Box der Startseite und wie früher in der currentInfoBar. */
.actions .moreFlyout.nowPlayingFlyout a {
	color: #6af;
	display: block;
	padding: 0;
	width: auto;
}

/* Mediathek-Darstellung ------------------------------------------------------------------------ */

/* Bei einer mit TMDB verknüpften Aufnahme steht links das Bild und rechts der Textblock; der Link umfasst
   beides (siehe inc/nowPlaying.html). Spezifität 0,4,1, um das display:block der Regel darüber zu schlagen. */
.actions .moreFlyout.nowPlayingFlyout a.nowPlayingLink {
	align-items: center;
	display: flex;
	flex: 1 1 auto;
	gap: 0.6em;
	min-width: 0;
}

/* "Stretched link": der Link deckt über sein Pseudo-Element die ganze Box ab, obwohl er im Markup nur Bild
   und Text umschließt. Ein <a> um die ganze Box wäre ungültig, sobald darin Schaltflächen stehen - so bleibt
   er ein richtiger Link (Mittelklick, Tastatur, Kontextmenü) und die Schaltflächen bleiben erreichbar.
   Nebenwirkung: Text im Kasten lässt sich nicht mehr markieren, in einer Kopfzeile vertretbar. */
.nowPlayingLink::after {
	content: "";
	inset: 0;
	position: absolute;
}

/* Die Schaltflächen müssen über die aufgezogene Fläche. Beide sind positioniert, der z-index steht trotzdem
   ausdrücklich da, damit die Absicht lesbar ist. Das Tonspur-Menü liegt als Nachfahre mit darüber. */
.nowPlayingTmdbBox .nowPlayingButtons {
	position: relative;
	z-index: 1;
}

/* Höhe fest, Breite über das Seitenverhältnis - so trägt ein Element beide Formen: Poster beim Film (2:3),
   Szenenbild bei einer Folge (16:9). flex:none ist zwingend, sonst quetscht der Flex-Container das Bild und
   das Verhältnis kippt. */
.nowPlayingImage {
	background-color: var(--page-bg);
	border-radius: 4px;
	flex: none;
	height: 4.5rem;
	overflow: hidden;
}

.nowPlayingImage.poster {
	aspect-ratio: 2 / 3;
}

.nowPlayingImage.still {
	aspect-ratio: 16 / 9;
}

.nowPlayingImage img {
	display: block;
	height: 100%;
	object-fit: cover;
	width: 100%;
}

/* Bewusst der Kindselektor bzw. .toggleMoreFlyout und nicht schlicht "button": im Tonspur-Menü, das seit Neuestem
   in diesem Menü steckt, hat jede Zeile eine Schaltfläche - die sollen ihre eigenen Maße behalten und nicht die
   der vier Bedienelemente hier. Ohne die Eingrenzung standen die Lautsprecher-Symbole dort nicht mehr in einer
   Spalte, weil Innenabstand und Schriftgröße der Zeilen überschrieben wurden. */
.moreFlyout.nowPlayingFlyout .nowPlayingButtons > button,
.moreFlyout.nowPlayingFlyout .nowPlayingButtons .toggleMoreFlyout {
	display: inline-flex;
	font-size: 1.2rem;
	padding: 0 5px;
	width: auto;
}

.moreFlyout.nowPlayingFlyout .nowPlayingButtons > button i,
.moreFlyout.nowPlayingFlyout .nowPlayingButtons .toggleMoreFlyout i {
	font-size: inherit;
}

/* Drei Zeilen plus Balken müssen in die 4rem hohe Kopfzeile passen: 1.15 statt 1.2 bringt gut 2px, die am Ende
   den Unterschied zwischen "passt" und "drückt die Kopfzeile auf" machen. Der Rest der Höhe geht als gap in die
   Zeilenabstände - bei einer Aufnahme großzügiger, weil dort eine Zeile weniger steht (siehe .nowPlayingMovie). */
.nowPlayingMain {
	display: flex;
	flex-direction: column;
	gap: 0.1875em; /* 3px bei der Grundgröße; in em, damit es der größeren Schrift auf dem Handy folgt */
	justify-content: center;
	line-height: 1.15;
	min-width: 0;
}

.nowPlayingMovie .nowPlayingMain {
	gap: 0.5em;
}

/* Der großzügige Abstand darüber gilt der zweizeiligen Aufnahme-Darstellung. In der Mediathek-Darstellung hat eine
   Serienfolge aber drei Zeilen (Serie, Folgentitel, Meta-Angaben) - dort wieder der engere Abstand der TV-Variante,
   sonst stehen sie zu weit auseinander und der Kasten sprengt fast die Kopfzeile.
   Die Unterscheidung über :has(.nowPlayingDesc) statt über eine eigene Klasse, weil es genau darum geht: die
   mittlere Zeile gibt es nur bei einer Folge, beim Film bleiben es zwei Zeilen. */
.nowPlayingTmdbBox .nowPlayingMain:has(.nowPlayingDesc) {
	gap: 0.1875em;
}

/* Bei einer Aufnahme steht das Auflösungssymbol hier statt in der entfallenen Senderzeile. */
.nowPlayingTitleRow {
	align-items: center;
	display: flex;
	gap: 0.4em;
	min-width: 0;
}

/* Flex, weil die Glyphe sonst rund 1.5px zu hoch in ihrem Kästchen sitzt: dessen Zeilenbox reserviert unter dem
   Symbol Platz für Unterlängen. Derselbe Effekt wie bei den Schaltflächen der Kopfzeile, siehe .globalActions
   .iconBtn - hier fällt er nur stärker auf, weil daneben eine Textzeile steht. */
/* color ausdrücklich, weil in der Mediathek-Darstellung die ganze Titelzeile im Link liegt und dessen Blau sonst
   auch das Auflösungssymbol einfärbt. In der Darstellung ohne TMDB ist der Wert derselbe wie der geerbte, dort
   ändert die Regel also nichts. */
.nowPlayingTitleRow .videoSizeIcon {
	align-items: center;
	color: var(--control-text);
	display: inline-flex;
	flex: none;
	font-size: 0.75rem;
}

/* font-size etwas kleiner als die geerbte Grundgröße - dieselbe wie beim Titel in der Info-Box der Startseite
   (.content .db-row, 0.9rem).
   Titel und Untertext sind die einzigen Teile, die schrumpfen dürfen. Damit das greift, muss die min-width:0-Kette
   von .globalActions bis hierher lückenlos sein - ein Flex-Kind schrumpft sonst nie unter seine Inhaltsbreite und
   der Kasten schöbe die Schaltflächen aus der Kopfzeile.
   Die Farbe steht bewusst nicht hier, sondern bei ".actions .moreFlyout.nowPlayingFlyout a": der Titel ist ein
   Link, und jene Regel hätte die höhere Spezifität. */
.nowPlayingTitle {
	font-size: 0.9rem;
	font-weight: bold;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Zeile 2: die Kurzbeschreibung der Sendung bzw. der Aufnahme. Etwas heller als die Senderzeile darunter, damit
   die Reihenfolge Titel - Inhalt - Herkunft auch farblich abgestuft ist. */
.nowPlayingDesc {
	color: #ccc;
	font-size: 0.75em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.nowPlayingSub {
	align-items: center;
	color: #aaa;
	display: flex;
	font-size: 0.75em;
	gap: 0.4em;
	min-width: 0;
}

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

.nowPlayingRemaining {
	flex: none;
}

/* gap in em, damit der Abstand der Vergrößerung auf dem Handy folgt (siehe Media Query). Er kommt zu den 5px
   Innenabstand je Schaltfläche hinzu.
   Einzeilig - im aufgeklappten Menü steht die Reihe unter dem Text und hat die volle Breite. Zweizeilig wird sie
   erst im Inline-Zustand, wo die Höhe da ist und die Breite knapp (siehe Media Query). */
.nowPlayingButtons {
	align-items: center;
	display: flex;
	flex: none;
	gap: 0.5em;
}

/* Die beiden Sprungknöpfe sehen aus wie ihre Nachbarn; ohne Ziel bleiben sie als ausgegraute Attrappe stehen,
   damit die Anordnung nicht springt. Farbe wie bei .tmdbTitleNav .disabled. */
.nowPlayingNav.disabled {
	color: var(--text-faint);
	cursor: default;
}

/* Binge-Modus. Bewusst größer als seine sechs Nachbarn: Er schaltet einen Zustand um, der über das Ende der
   laufenden Folge hinaus wirkt, während die anderen sechs Einzelaktionen auslösen - und er steht als einziger
   allein in seiner Rasterspalte, wo die zusätzliche Größe niemanden verdrängt.
   Der lange Selektor ist nötig: ".moreFlyout.nowPlayingFlyout .nowPlayingButtons > button i" weiter oben setzt
   mit (0,4,2) "font-size: inherit" und schlüge jede kürzere Fassung. Und em statt rem, damit die Vergrößerung
   auch im Handy-Menü greift, wo die Schaltflächen selbst schon größer sind. */
.moreFlyout.nowPlayingFlyout .nowPlayingButtons > button.nowPlayingBinge i {
	font-size: 1.4em;
}

/* Der eingeschaltete Zustand allein über die Farbe - blau wie der Titel und der Umschalter des Kastens. Anders
   als dort wird bewusst nicht zusätzlich auf die gefüllte Symbolvariante umgeschaltet: Die gefüllte
   Unendlichkeitsschleife verliert ihre Form, weil die Innenflächen der beiden Schlaufen zulaufen.
   ".globalActions" davor, weil ".iconBtn { color: white }" bei gleicher Spezifität weiter unten in der Datei
   steht - dieselbe Falle wie beim .nowPlayingToggle. */
.globalActions .nowPlayingBinge.active {
	color: #6af;
}

/* Die Symbole sind mit 29x19px zu klein, um sie mit dem Finger sicher zu treffen - danebengetippt löst man die
   aufgezogene Fläche des Titel-Links aus und landet auf der Detailseite. Ein unsichtbares Pseudo-Element
   vergrößert deshalb nur die Trefferfläche, ohne am Aussehen etwas zu ändern.
   4px je Seite ist das Maximum ohne Überlappung: zwischen den Schaltflächen liegen 8px, zwischen den beiden
   Zeilen des Rasters 8.8px - die vergrößerten Flächen stoßen also gerade aneinander. */
.nowPlayingButtons > button,
.nowPlayingButtons .toggleMoreFlyout {
	position: relative;
}

.nowPlayingButtons > button::after,
.nowPlayingButtons .toggleMoreFlyout::after {
	content: "";
	inset: -4px;
	position: absolute;
}

/* Der Balken ist hier kein eigener Streifen wie in den Timer-Listen, sondern nur ein dünner Trenner zwischen
   Kurzbeschreibung und Senderzeile - die 0.5em Höhe von .timerProgress wären dafür viel zu wuchtig und kosteten
   die Zeile, die stattdessen die Beschreibung bekommt. Zwei Klassen, weil .timerProgress weiter unten in der
   Datei steht und bei gleicher Spezifität über die Quellreihenfolge gewänne. */
/* margin: 0 gehört ausdrücklich dazu: ".timerProgress .timerProgressBar" gibt dem gefüllten Teil sonst 0.2em
   Außenabstand mit, und der rutscht bei 2px Höhe sichtbar aus seiner Spur heraus - es sieht dann nach zwei
   Strichen aus statt nach einem Balken. */
.nowPlayingMain .nowPlayingProgress,
.nowPlayingMain .nowPlayingProgress .timerProgressBar {
	border-radius: 1px;
	height: 2px;
	margin: 0;
}


/* Die Größe steht an der Schaltfläche, nicht am Symbol: der Tonspur-Auslöser trägt bewusst "font-size: inherit"
   an seinem <i> (siehe .audioTrackActions .toggleMoreFlyout i), passt sich also seinem Umfeld an - und dieses
   Umfeld ist genau diese Regel. Nicht auf .rcBtn eingegrenzt, weil weder Info- noch Tonspur-Knopf einer ist. */
/* Der Tonspur-Auslöser steckt als einziger der vier in einem .actionWrapper (er bringt ja sein eigenes Menü mit).
   Dessen inline-block aus ".audioTrackActions .actionWrapper" richtet ihn an der Grundlinie aus statt mittig, und
   er säße dadurch 1.4px höher als seine drei Nachbarn. Drei Klassen, weil jene Regel weiter unten in der Datei
   steht und bei Gleichstand gewönne. */
.actions .nowPlayingButtons .actionWrapper {
	align-items: center;
	display: flex;
}


/* Ab hier der Inline-Zustand. Bewusst als min-width-Block, obwohl die Datei sonst desktop-first ist: andernfalls
   müsste ein max-width-Block den Popup-Zustand mit kopierten Werten (Fläche, Rahmen, Innenabstand, absolute
   Positionierung) wiederherstellen, die bei einer Änderung an .actions .moreFlyout stillschweigend auseinanderliefen.
   So bleibt der Flyout-Zustand der unangetastete Originalzustand. */
@media (min-width: 1025px) {
	/* margin-left hält den Kasten vom Logo weg - ohne ihn beginnt der Titel unmittelbar an dessen Kante, weil der
	   Kasten den freien Bereich ja gerade ausfüllen soll. */
	.nowPlayingActions {
		flex: 1 1 auto;
		margin-left: 1.5rem;
	}

	/* .globalActions davor ist nötig: ".globalActions .iconBtn { display: inline-flex }" hätte sonst die höhere
	   Spezifität, und eine Media Query ändert daran nichts. */
	.globalActions .nowPlayingToggle {
		display: none;
	}

	.actions .moreFlyout.nowPlayingFlyout {
		align-items: center;
		background-color: transparent;
		border: none;
		display: flex;
		flex-direction: row;
		margin-top: 0;
		padding: 0;
		position: static;
	}

	/* Der Kasten muss Bezugspunkt für das aufgezogene Pseudo-Element bleiben. Ohne das spannte es sich bis zur
	   Kopfzeile auf - die ist positioniert - und schluckte die Klicks auf Ein/Aus und Fernbedienung.
	   .nowPlayingTmdbBox sitzt am äußeren .actions-Element, nicht am Menü selbst; vier Klassen, damit die Regel
	   darüber (0,3,0, im selben Block) sicher geschlagen wird. */
	.actions.nowPlayingTmdbBox .moreFlyout.nowPlayingFlyout {
		position: relative;
	}

	/* In der 4rem hohen Kopfzeile kleiner als im Flyout: 3rem entspricht der Höhe des Logos. */
	.nowPlayingImage {
		height: 3rem;
	}

	/* Die Breitenbegrenzung gilt dem aufgeklappten Menü, damit es auf dem Handy nicht über den Rand läuft. Inline
	   ist sie schädlich: der Kasten hört dann mitten im freien Bereich auf und kürzt seine Zeilen mit "...", obwohl
	   rechts noch Platz ist. Begrenzt wird er hier ohnehin durch die Flex-Kette - er wächst nur bis an die
	   Schaltflächen und schrumpft davor über min-width:0 (siehe .nowPlayingLink). */
	.globalActions .actions .moreFlyout.nowPlayingFlyout {
		max-width: none;
	}

	/* Sechs Schaltflächen inline: als 3x2-Raster statt in einer Reihe. Das spart rund 37px Breite gegenüber einer
	   Reihe (die stattdessen 74px mehr bräuchte) und kostet nur Höhe, die in der 4rem hohen Kopfzeile neben dem
	   52px hohen Textblock ohnehin da ist. Bei 1025px sind links nur rund 628px frei - dort zählt die Breite.
	   Ein Raster statt flex-wrap, weil die Umbruchstelle so festliegt und nicht von den Buttonbreiten abhängt.
	   Nur mit den Sprungknöpfen: ohne sie sind es vier Schaltflächen (Film) bzw. zwei (Fernsehen), und die
	   stünden im Dreierraster als 3+1 da - Stopp allein in der zweiten Zeile. */
	.nowPlayingButtons:has(.nowPlayingNav) {
		display: grid;
		grid-template-columns: repeat(3, auto);
	}

	/* Die vierte Spalte nur, wenn der Binge-Schalter auch da ist. Sie einfach immer zu deklarieren wäre falsch:
	   Eine leere Spur fällt zwar auf Breite 0 zusammen, aber die automatische Platzierung füllt sie vorher auf -
	   ohne den Schalter stünden die sechs übrigen dann als 4+2 statt als 3+3 (gemessen). */
	.nowPlayingButtons:has(.nowPlayingNav):has(.nowPlayingBinge) {
		grid-template-columns: repeat(3, auto) auto;
	}

	/* Der Schalter bekommt die vierte Spalte über beide Zeilen und steht darin mittig. Die feste Platzierung
	   nimmt ihn aus dem automatischen Fluss, die übrigen sechs verteilen sich also unverändert auf 1-3. */
	.nowPlayingButtons:has(.nowPlayingNav) .nowPlayingBinge {
		align-self: center;
		grid-column: 4;
		grid-row: 1 / span 2;
	}

	/* Die drei Wiedergabe-Schaltflächen gemeinsam in die zweite Zeile, damit sie dort als zusammenhängende
	   Leiste "zurück - Wiedergabe - vor" stehen. In der Markup-Reihenfolge umschließt die Navigation die
	   Wiedergabe, was einzeilig richtig ist; im Dreierraster zerfiele sie sonst zeilenweise zu
	   "Beschreibung, Tonspur, zurück / Wiedergabe, vor, Stopp".
	   Über order statt über eine andere Markup-Reihenfolge, damit die einzeilige Anordnung unberührt bleibt. */
	.nowPlayingButtons:has(.nowPlayingNav) .nowPlayingNav,
	.nowPlayingButtons:has(.nowPlayingNav) [data-rc="play"] {
		order: 1;
	}
}

.remoteFlyout {
	height: fit-content;
	margin: 0 0.5rem 0 0;
	position: sticky;
	scrollbar-gutter: stable;
	top: 5rem;
}

.remoteFlyout .remote {
	margin: 0;
}

#remoteFlyout {
	display: none;
}
#remoteFlyout.open {
	display: block;
}

/* Flyout Menu ---------------------------------------------------------------------------------- */

.flyout-menu {
	background: linear-gradient(180deg, var(--page-bg), var(--surface));
	border-bottom: 1px solid var(--line);
	border-right: 1px solid var(--line);
	display: flex;
	flex-direction: column;
	gap: 0;
	left: 0;
	max-height: calc(var(--vh) * 100 - 4rem);
	opacity: 0;
	overflow-y: auto;
	padding: 0;
	pointer-events: none;
	position: fixed;
	top: 4rem;
	transform: translateX(-100%);
	transform-origin: left;
	transition: transform 0.3s ease, opacity 0.3s ease;
	width: 200px;
	z-index: 11;
}

.flyout-menu.open {
	opacity: 1;
	pointer-events: auto;
	transform: translateX(0);
}

.flyout-item {
	align-items: center;
	border-left: 3px solid transparent;
	color: #aaa;
	cursor: pointer;
	display: flex;
	gap: 0.75em;
	padding: 0.6em 1em;
	text-align: left;
	transition: all 0.2s ease;
	white-space: nowrap;
}

.flyout-item:active {
	background-color: rgba(102, 153, 221, 0.2);
	color: #fff;
}

.flyout-item.active {
	border-left-color: #6af;
	color: #6af;
	font-weight: bold;
}

/* Die Box-Umschalter sind eine Auswahl, kein Ort. Mit der Ortsmarkierung der Menüpunkte (Balken plus eingefärbte
   Schrift) sah es aus, als wäre man auf zwei Seiten gleichzeitig. Die gewählte Box bekommt deshalb die Optik einer
   Auswahlliste - gefüllte Fläche und Häkchen - und bewusst keinen Balken. */
.flyout-item.switchBox.active {
	background: var(--control-bg);
	border-left-color: transparent;
	color: var(--control-text);
}

.switchBoxCheck {
	display: none;
}

.switchBox.active .switchBoxCheck {
	display: inline-block;
	margin-left: auto;
}

.flyout-item i {
	font-size: 1.3rem;
	flex-shrink: 0;
}

.flyout-separator {
	border-top: 1px solid var(--line);
}

/* Bereichsgruppen wie auf der Startseite: Balken in der Gruppenfarbe links, wo er am schnellsten erfasst wird.
   Der Balken sitzt bewusst an den Einträgen selbst und nicht an der Gruppe - so läuft er ohne Lücke durch, und der
   aktive Eintrag kann sein eigenes Stück davon einfärben (Variante B unten). Getrennt werden die Gruppen durch eine
   Linie ohne Abstand, damit der Farbbalken eine durchgehende Spalte bleibt. */
.flyout-group + .flyout-group {
	border-top: 1px solid var(--line);
}

.flyout-group--recording .flyout-item { border-left-color: var(--group-recording); }
.flyout-group--mediathek .flyout-item { border-left-color: var(--group-mediathek); }
.flyout-group--misc      .flyout-item { border-left-color: var(--group-misc); }

/* Der aktive Eintrag hellt sein Stück des Gruppenbalkens auf, statt eine eigene Farbe einzuführen - so bleibt die
   Bereichszugehörigkeit auch in der Markierung lesbar. Schrift und Symbol gehen bewusst mit: ein grüner Balken neben
   hellblauer Schrift wären zwei Aussagen zur selben Zeile. */
.flyout-group--recording .flyout-item.active { border-left-color: var(--group-recording-bright); color: var(--group-recording-bright); }
.flyout-group--mediathek .flyout-item.active { border-left-color: var(--group-mediathek-bright); color: var(--group-mediathek-bright); }
.flyout-group--misc      .flyout-item.active { border-left-color: var(--group-misc-bright);      color: var(--group-misc-bright); }

/* Menüpunkte ohne Gruppe (derzeit nur "Einstellungen") bleiben auf der Grauachse, statt hellblau zu werden: Das
   Hellblau stand als vierte Farbe neben den drei Bereichsfarben und sah aus wie eine weitere Gruppe. Aufgehellt wird
   nach demselben Muster wie bei den Gruppen - der gedämpfte Grundton (#aaa, siehe .flyout-item) geht auf die normale
   Textstärke hoch. Reines Weiß wäre der Sprung ans obere Ende und dafür zu grell.
   Der Kindselektor trifft genau die gruppenlosen Einträge - die der Gruppen liegen eine Ebene tiefer in
   .flyout-group. Bewusst hier und nicht an .flyout-item.active: diese Klasse vergibt auch die Listen-Seitenleiste an
   die gewählte Liste (lists.js). */
.mainItems > .flyout-item.active {
	border-left-color: var(--text);
	color: var(--text);
}

/* Die Bereiche stehen im Flyout immer mit drin - auf breiten Bildschirmen doppelt zur Sidebar, dafür ist alles an
   einer Stelle erreichbar (u.a. "Einstellungen", das die Sidebar deshalb nicht mehr führt). */
.flyout-menu .mainItems {
	display: block;
}

.flyout-item.has-submenu {
	position: relative;
}
.flyout-item.has-submenu::after {
	content: "▼";
	display: inline-block;
	margin-left: auto;
}
.flyout-item.has-submenu.open::after {
	content: "▲";
}

.flyout-submenu .flyout-item {
	font-size: 0.9em;
    padding: 0.4em 1em 0.5em 1.6em;
}
.flyout-submenu .flyout-item:first-child {
	border-top: 1px dashed var(--line);
}
.flyout-submenu .flyout-item i {
    font-size: 1rem;
}

/* Sidebar -------------------------------------------------------------------------------------- */

.sidebar {
	border-right: 1px solid var(--line);
	display: flex;
	flex: 0 0 5.5rem;
	flex-direction: column;
	left: 0;
	height: calc(var(--vh) * 100 - 4rem);
	overflow-y: auto;
	/* Oben bewusst ohne Abstand: Der Farbbalken der ersten Gruppe soll direkt unter dem Seitenkopf ansetzen - eine
	   Lücke sah nach abgerissener Spalte aus und kostete nur Höhe. Unten bleibt Luft für das Ende der Liste. */
	padding: 0 0 0.75em 0;
	position: sticky;
	top: 4rem;
	transition: width 0.3s ease;
	/* Unter den Aktionsmenüs (z-index 8, siehe .actions .moreFlyout): Ein Menü der ersten Kachel reicht bis über die
	   Navigationsleiste, und lag diese darüber, schienen ihre Symbole durch das Menü hindurch - sie hat keinen eigenen
	   Hintergrund. Über dem Seiteninhalt bleibt sie damit trotzdem. */
	z-index: 7;
}

.nav-btn {
	align-items: center;
	background: transparent;
	border: none;
	border-left: 3px solid transparent;
	color: #aaa;
	cursor: pointer;
	display: flex;
	flex-direction: column;
	font-size: 0.65rem;
	gap: 0.3em;
	justify-content: center;
	min-height: 5em;
	padding: 0.5em;
	text-align: center;
	transition: font 0.3s ease;
	width: 100%;
}

.nav-btn i {
	font-size: 1.7rem;
}

.nav-btn:active {
	color: #fff;
}

.nav-btn.active {
	border-left-color: #6af;
	color: #6af;
}

/* Bereichsgruppen wie im Flyout und auf der Startseite: Balken in der Gruppenfarbe links, wo er am schnellsten
   erfasst wird.
   Der Balken wird hier als Hintergrund der Gruppe gezeichnet und nicht als Rahmen der Schaltflächen. Nur so trägt er
   die Innenabstände mit: Die Gruppen brauchen Luft zueinander und zum Seitenkopf, ein Abstand zwischen den
   Schaltflächen würde den Balken aber zerhacken. Als Rahmen der Schaltfläche bliebe er dagegen exakt so hoch wie die
   Schaltfläche selbst.
   Die Schaltflächen behalten ihren 3px-Rahmen links, der im Normalfall durchsichtig ist und den Gruppen-Hintergrund
   durchscheinen lässt - der aktive Eintrag färbt ihn ein und überdeckt damit passgenau sein Stück des Balkens. */
.nav-group {
	padding: 0.4em 0;
}

.nav-group + .nav-group {
	border-top: 1px solid var(--line);
}

.nav-group--recording { background: linear-gradient(to right, var(--group-recording) 3px, transparent 3px); }
.nav-group--mediathek { background: linear-gradient(to right, var(--group-mediathek) 3px, transparent 3px); }
.nav-group--misc      { background: linear-gradient(to right, var(--group-misc) 3px, transparent 3px); }

/* Der aktive Bereich hellt sein Stück des Balkens auf und färbt Schrift und Symbol mit - wie im Flyout, damit
   dieselbe Markierung nicht in zwei Navigationen unterschiedlich aussieht. */
.nav-group--recording .nav-btn.active { border-left-color: var(--group-recording-bright); color: var(--group-recording-bright); }
.nav-group--mediathek .nav-btn.active { border-left-color: var(--group-mediathek-bright); color: var(--group-mediathek-bright); }
.nav-group--misc      .nav-btn.active { border-left-color: var(--group-misc-bright);      color: var(--group-misc-bright); }

.sidebar-spacer {
	flex: 1;
}

/* Main ----------------------------------------------------------------------------------------- */

main {
	display: flex;
	gap: 1rem;
	justify-content: space-between;
	margin-top: 4rem;
	padding: 0;
}

/* min-width: 0 hebt den Standardwert "auto" für Flex-Kinder auf, der ein Element nie unter seine Inhaltsbreite
   schrumpfen lässt. Ohne ihn wächst der gesamte Inhaltsbereich mit seinem breitesten Kind mit (statt sich auf die
   Fensterbreite zu beschränken), und innenliegende Bereiche mit overflow-x kommen nie zum Zug: sie haben ja
   scheinbar Platz. Aufgefallen an der Videoreihe einer Serie mit vielen Videos, die die Seite auf ~2260px zog. */
/* Rechts bewusst genauso viel Luft wie links (dort kommt sie aus dem gap zur .sidebar): Ohne eigenes
   padding-right klebte der Inhalt am rechten Rand, sobald kein Formular in .editForm daneben sitzt - das betrifft
   die meisten Seiten. Wirkt sich auf ein offenes Formular nicht aus, weil das ein eigenes Flex-Geschwister von
   main-content ist und dessen rechte Kante unverändert am main-Rand bleibt (siehe .editForm). Unterhalb von
   1024px (siehe dortige Media Query) verschwindet die Sidebar ohnehin, dort bleibt es daher beim alten,
   randlosen Verhalten. */
.main-content {
	flex: 1;
	min-width: 0;
	padding: 0 1em 1em 0;
}

/* Content -------------------------------------------------------------------------------------- */

.errorCode {
	color: #999;
}

.errorDetails {
	background-color: var(--surface);
	color: #ccc;
	font-family: monospace;
	font-size: 1rem;
	padding: 1rem;
	white-space: pre-wrap;
}

.infoBar {
	align-items: center;
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 0.5rem 1rem;
	margin: 1rem 0;
}

/* Auch innerhalb der Zählzeile eine Flex-Zeile: dort stehen Schaltflächen zwischen Fließtext, und im Textfluss
   richten sie sich an der Schriftlinie aus statt an der Mitte - eine 2rem hohe Schaltfläche saß dadurch sichtbar
   höher als der Text daneben. */
.countInfo {
	align-items: center;
	column-gap: 0.25rem;
	display: flex;
	flex-wrap: wrap;
	row-gap: 0.4rem;
}

/* Auf Leisten mit .flowBar fließen Angaben und Schaltflächen in einem gemeinsamen Fluss: sonst ist die Zählzeile
   ein einzelnes Flex-Element, und sobald ihr Inhalt umbricht, wird sie zweizeilig - die Schaltflächen dahinter
   können dann nicht mehr neben ihrer letzten Zeile stehen und rutschen komplett darunter (auf einem schmalen
   Handy ergab das vier Zeilen statt zwei).
   Der gesamte Abstand kommt hier aus dem gap und nicht aus margins: ein gap fällt am Zeilenanfang weg, ein
   margin nicht - eine umbrochene Zeile begänne sonst sichtbar eingerückt. Die Trennzeichen der Seite dürfen
   dafür keine eigenen Leerzeichen mitbringen, sie sind eigenständige Elemente des Flusses. */
.infoBar.flowBar {
	column-gap: 0.4rem;
}

.infoBar.flowBar .countInfo {
	display: contents;
}

/* Der führende Reload-/Refresh-Button steht etwas abgesetzt: er ist eine Aktion, während rechts davon die
   Angaben der Seite folgen - ohne den Abstand liest er sich wie deren erstes Zeichen. */
.countInfo > .iconBtn:first-child {
	margin-right: 0.5rem;
}

/* Eine einzelne Angabe der Zählzeile - Symbol und Zahl gehören zusammen und dürfen nicht getrennt werden. */
.countItem {
	white-space: nowrap;
}

/* Eine Ergänzung in Klammern hinter einer Angabe ("274 Filmreihen (191 komplett)", siehe tmdbmovies.html). Sie
   erläutert die Zahl davor und tritt deshalb zurück, statt als zweite Angabe gelesen zu werden. */
.countSub {
	color: var(--text-muted);
}

/* Icon-Schriften wie Phosphor füllen ihr Zeichen nahezu bis zum Schriftrand aus und setzen dessen Unterkante exakt
   auf die Grundlinie - eine Ziffer dagegen hat keine Unterlänge und wirkt dadurch, an derselben Grundlinie
   ausgerichtet, sichtbar tiefer als das Symbol daneben. vertical-align:middle behebt das: Es richtet die Mitte des
   Symbols an der Mitte der x-Höhe der Ziffern aus, was optisch sehr nah an eine echte Zentrierung herankommt. */
.countItem i {
	vertical-align: middle;
}

/* Rein per CSS gezeichnet statt des Zeichens "&triangleright;": dessen Position im Glyphen ist von Schriftart zu
   Schriftart verschieden (mal mittig, mal deutlich Richtung Grundlinie) und lässt sich deshalb nicht zuverlässig
   zentrieren - dieses Dreieck dagegen sitzt unabhängig von der Schriftart exakt mittig zur Zeile. em-Einheiten,
   damit es mit der Schriftgröße der Zählzeile mitskaliert; currentColor, damit es dieselbe Farbe wie der Text hat. */
.sepTriangle {
	border-bottom: 0.22em solid transparent;
	border-left: 0.4em solid currentColor;
	border-top: 0.22em solid transparent;
	display: inline-block;
	height: 0;
	vertical-align: middle;
	width: 0;
}

/* Der "verwaist"-Zähler ist als einziger Zähler eine Schaltfläche (er setzt den zugehörigen Filter, siehe
   listFilter.js#data-filter-shortcut). Er soll sich trotzdem nahtlos in die Zählerzeile einreihen - daher ohne
   Rahmen und Hintergrund, nur in Warnfarbe und mit Zeigerhand. */
.countInfo .showMissingBtn {
	background: none;
	border: none;
	color: #d44;
	cursor: pointer;
	font: inherit;
	padding: 0;
}

/* Der Pfad ist aus einzelnen Links je Verzeichnisebene aufgebaut; der column-gap der Zeile würde ihn
   auseinanderreißen ("/hdd/ !TV/" statt "/hdd/!TV/"). Er läuft deshalb ohne Lücke durch, und die Schaltflächen
   dahinter holen sich ihren Abstand selbst - sie sollen sich deutlich vom Pfad und voneinander absetzen. */
.infoBar .breadcrumb {
	column-gap: 0;
}

/* :not(:first-child), weil dieselbe Zeile auf der Ordnerübersicht mit dem Reload-Button beginnt - der soll
   bündig mit dem übrigen Seiteninhalt stehen und nicht eingerückt sein. */
.infoBar .breadcrumb > .iconBtn:not(:first-child) {
	margin-left: 0.6rem;
}

.countInfo .prevNextButtons {
	margin-left: 1rem;
}

.countLabel {
	display: inline;
}

/* Das Seitensymbol tritt auf schmalen Bildschirmen an die Stelle der Beschriftung (siehe Media Query). Den
   Abstand zur Zahl trägt ein echtes Leerzeichen im Markup - genau wie bei den übrigen Angaben, damit er dort
   und hier identisch ist. Auf breiten Bildschirmen steht davor die Beschriftung mit eigenem Leerzeichen; beide
   fallen zusammen, weil HTML aufeinanderfolgende Leerzeichen zu einem zusammenzieht. */
.countIcon {
	display: none;
}

.filter .checkBox {
	display: none;
}

.filter .checkBox:checked + .checkLabel {
	background-color: var(--control-bg-hover);
	color: var(--control-text-hover);
	font-weight: bold;
}

.filter .checkLabel {
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: 3px;
	color: #ddd;
	cursor: pointer;
	display: inline-block;
	font-size: 0.9em;
	margin: 0 0.5em 0.25em 2em;
	padding: 3px 5px;
}

/* Filterleiste: standardmäßig zugeklappt, wird über den Trichter-Button in der .infoBar geöffnet. */
/* Bewusst ohne eigene Fläche und ohne Rahmen: die Filterleiste besteht bereits aus lauter umrandeten
   Bedienelementen, ein Kasten darum ergab einen Rahmen im Rahmen. Ohne Innenabstand fluchten ihre Elemente
   zudem mit dem übrigen Seiteninhalt statt eingerückt zu stehen. */
.filterBar {
	align-items: center;
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	/* Waagerecht enger als eine übliche Bedienzeile: seit die Filter Symbol-Knöpfe statt Pillen-Gruppen sind,
	   trennt schon der eigene Rahmen jedes Elements sie deutlich genug voneinander. Senkrecht dagegen mehr, denn
	   auf schmalen Geräten bricht die Leiste um: Stünden die Zeilen genauso eng wie die Elemente darin, verschwämmen
	   sie zu einer Fläche, statt als zwei Zeilen lesbar zu sein. */
	gap: 0.6rem 0.5rem;
	margin: 0 0 1rem 0;
	padding: 0;
}

.filterBar[hidden] {
	display: none;
}

/* Suchfeld + Suchfelder-Flyout-Button ohne Abstand aneinandergedockt, sodass nur eine gemeinsame
   Border-Linie an der Nahtstelle sichtbar ist (wirkt wie ein Element mit integriertem Button): */
.filterSearchGroup {
	display: inline-flex;
}

.filterSearchGroup .filterSearch {
	border-bottom-right-radius: 0;
	border-right: none;
	border-top-right-radius: 0;
}

.filterSearchGroup .filterFlyoutToggleBtn {
	border-bottom-left-radius: 0;
	border-top-left-radius: 0;
}

/* Ganz schmale Geräte: das Suchfeld gibt Breite ab, damit die Filterleiste in zwei statt drei Zeilen passt.
   Beide Zahlen sind gemessen, nicht geschätzt (Filmübersicht, deren Leiste die meisten Filter trägt): Mit der
   vom Browser vorgegebenen Feldbreite von 200px reicht es bis 404px Fensterbreite für zwei Zeilen, ab 400px
   bricht die dritte auf - daher genau hier die Grenze. Und 6,5rem ist die größte Breite, mit der auch die
   verbreiteten 360px-Geräte noch mit zwei Zeilen auskommen (ab 116px wird es dort wieder dreizeilig). Bei
   320px hilft übrigens keine Feldbreite mehr, dort bleiben es drei Zeilen. */
@media (max-width: 400px) {
	.filterBar .filterSearch {
		width: 6.5rem;
	}
}

/* .defaultSelect ist an anderen Stellen der App (Edit-Formulare etc.) bewusst größer - hier an die
   Höhe von .filterSearch (input[type="search"]) angleichen, damit alle Elemente der Filterleiste
   gleich hoch sind: */
.filterBar .defaultSelect {
	height: var(--control-height);
	padding: 0 2rem 0 0.75rem;
}

/* Der Innenabstand bleibt halb so groß wie der zwischen den Filtern (siehe .filterBar), sonst verwischt die
   Gruppierung: die Pillen einer Gruppe stünden genauso weit auseinander wie die Gruppen selbst. */
.filterBar .filterGroup {
	align-items: center;
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 0.25rem;
}

/* Anker für das Kennzeichen mit der Trefferzahl. Es hängt am Trichter-Umschalter, damit auch zugeklappt
   sichtbar bleibt, dass gefiltert wird - und bei dauerhaft offener Leiste (Filme, Serien), die keinen
   Umschalter mehr hat, stattdessen am Zurücksetzen-Knopf. */
.filterToggleBtn,
.filterResetBtn {
	position: relative;
}

/* Zeigt die Anzahl der Einträge, die der Filter übrig lässt (siehe listFilter.js). Pillenform statt Kreis:
   bei großen Sammlungen wird die Zahl vierstellig, ein 50%-Radius ergäbe dann eine Ellipse. Das Badge wächst
   nach links (rechte Kante steht fest) und darf dabei nicht umbrechen. */
.filterBadge {
	background-color: #c33;
	border-radius: 999px;
	color: #fff;
	font-size: 0.7rem;
	line-height: 1rem;
	min-width: 1rem;
	padding: 0 0.25rem;
	position: absolute;
	right: -0.3rem;
	text-align: center;
	top: -0.3rem;
	white-space: nowrap;
}

/* Das Kennzeichen überlappt die obere rechte Ecke seines Knopfes. Am Trichter-Umschalter ist das unkritisch -
   dort erscheint es nur beim Filtern, und dann ist die Zahl die wichtigere Auskunft. Am Zurücksetzen-Knopf
   einer offenen Leiste steht es dagegen dauerhaft und schnitte den Trichter sonst immer oben an; sein Symbol
   rückt deshalb ein Stück nach unten. Leicht aus der Mitte ist das kleinere Übel als dauerhaft verdeckt. */
.filterResetBtn:has(.filterBadgePermanent) > i {
	transform: translateY(3px);
}

/* Ruhezustand des dauerhaften Kennzeichens: dieselbe Pille, aber im Blau der Bedienelemente statt in Rot.
   Rot heißt hier durchgehend "eingeschränkt" - ungefiltert ist die Zahl nur eine Auskunft und darf nicht so
   aussehen, als sei etwas ausgeblendet. */
.filterBadge.filterBadgeIdle {
	background-color: var(--control-bg-hover);
	color: var(--control-text);
}

.filterBadge[hidden] {
	display: none;
}

/* Ausgefilterte Einträge. Der zweite Selektor ist kein Versehen: .tmdbTile setzt weiter unten selbst
   display:flex, und bei gleicher Spezifität (je eine Klasse) gewinnt die später notierte Regel - die
   Kacheln blieben dadurch trotz gesetzter Klasse sichtbar. Eine Kachelart, die eigenes display braucht,
   muss hier deshalb mit aufgeführt werden (Tabellenzeilen brauchen das nicht). */
.filterHidden,
.tmdbTile.filterHidden {
	display: none;
}

.filterNoMatch {
	color: #aab;
	font-style: italic;
	margin: 1rem 0;
}

.filterNoMatch[hidden] {
	display: none;
}

/* Generisches Flyout: Button + darunter aufklappendes Panel, Optik analog zu .autoTimerActionFlyout.
   Von mehreren Filtern gemeinsam genutzt (Tags, Status, ggf. weitere) - siehe listFilter.js, das jedes
   .filterFlyoutWrapper innerhalb einer .filterBar generisch öffnen/schließen kann. */
.filterFlyoutWrapper {
	position: relative;
}

.filterFlyoutToggleBtn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--field-radius);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-size: 0.9em;
	gap: 0.3rem;
	height: var(--control-height); /* gleiche Höhe wie die übrigen Elemente der Filterleiste */
	padding: 0 0.6rem;
}

.filterFlyoutToggleBtn:active:not(:disabled):not(.active) {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

/* Gleiche Highlight-Farbe wie im Hauptmenü (.flyout-item.active), damit hier kein neuer Blauton entsteht: */
.filterFlyoutToggleBtn.active {
	background-color: rgba(102, 153, 221, 0.3);
	border-color: #6af;
	color: #6af;
	font-weight: bold;
}

.filterFlyoutToggleBtn:disabled {
	cursor: default;
	opacity: 0.5;
}

.filterFlyoutCount {
	background-color: #c33;
	border-radius: 50%;
	color: #fff;
	font-size: 0.7rem;
	line-height: 1rem;
	min-width: 1rem;
	padding: 0 0.3rem;
	text-align: center;
}

.filterFlyoutCount[hidden] {
	display: none;
}

/* Zugeklappt bewusst display:none statt nur visibility:hidden: ein lediglich unsichtbares Panel behält
   seine Ausmaße und schiebt, sobald es rechts über den Fensterrand hinausreicht, den Scrollbereich der
   Seite auf - beim Aufklappen der Filterleiste entstand dadurch rechts ein leerer Streifen, obwohl die
   Leiste selbst bequem in eine Zeile passte. Ohne Fläche kann es das nicht mehr (wie beim "..."-Menü,
   siehe .actions .moreFlyout). Beim aufgeklappten Panel hält positionFlyout() den Rand ein.

   Rechtsbündig statt linksbündig verankert (wächst nach links auf): die meisten Flyouts (Genre/Kategorie/
   Tags/Reset, aber auch der Suchoptionen-Flyout direkt neben dem schmalen Suchfeld) stehen in der Filterleiste
   eher gegen deren Ende bzw. ihr eigener Umschalter ist schmaler als das Panel. Bei linksbündiger Verankerung
   entsteht dort für einen Layout-Durchgang eine über den rechten Fensterrand hinausragende Fläche, bevor
   positionFlyout() sie per transform zurückschiebt - transform korrigiert zwar die Bildschirmposition, nicht
   aber die von manchen mobilen WebViews (App-Shell) herangezogene Layoutbreite, die daraufhin die ganze Seite
   herauszoomt (siehe auch Kommentar oben zum zugeklappten Zustand - dasselbe Prinzip, nur beim Öffnen statt
   beim Schließen). Rechtsbündig legt das Panel dabei auch optisch näher an das zugehörige Suchfeld statt
   seitlich daneben. */
.filterFlyoutPanel {
	background-color: var(--surface-raised);
	border: 1px solid var(--control-border);
	border-radius: 10px; /* wie das "..."-Menü, siehe .actions .moreFlyout */
	display: none;
	flex-direction: column;
	left: auto;
	margin-top: 2px;
	min-width: 12rem;
	padding: 0.5rem;
	position: absolute;
	right: 0;
	top: 100%;
	z-index: 8; /* unter den festgehefteten Leisten, siehe .actions .moreFlyout */
}

.filterFlyoutPanel.open {
	display: flex;
}

/* Im Flyout-Panel sind die Einträge Menüzeilen, keine Chips: Fläche und Rahmen entfallen deshalb, nur das
   Kästchen bzw. der Punkt davor bleibt. Der Rahmen wird auf transparent gesetzt statt entfernt, damit die
   Zeilen ihre Breite behalten und beim Antippen nicht springen. */
.filterFlyoutPanel .defaultCheckboxLabel,
.filterFlyoutPanel .defaultRadioLabel {
	background-color: transparent;
	border-color: transparent;
	border-radius: 6px;
	padding: 0.25rem 0.4rem;
	white-space: nowrap;
}

/* border-color muss hier mit: die allgemeine Druck-Regel der Chips hellt ihn sonst auf, und beim Antippen
   blitzte der Rahmen wieder auf, den die Zeile gerade nicht haben soll. */
.filterFlyoutPanel .defaultCheckboxLabel:active,
.filterFlyoutPanel .defaultRadioLabel:active {
	background-color: rgba(102, 153, 221, 0.2);
	border-color: transparent;
	color: var(--control-text-hover);
}

/* Trennlinie zwischen zwei Gruppen innerhalb desselben Flyout-Panels (z.B. Status/aktiviert-deaktiviert): */
.filterFlyoutSeparator {
	border-top: 1px solid var(--control-border);
	margin: 0.4rem 0;
}

/* Bewusst ohne max-height und eigenen Scrollbereich: Die Liste wird lieber lang und schiebt das Panel nach unten
   aus dem Fenster, als sich in einen zweiten Scrollbereich innerhalb der Seite zu zwängen. Dann sieht man auf einem
   großen Bildschirm alle Einträge auf einen Blick, und auf einem kleinen scrollt man nur die Seite statt erst sie
   und darin nochmal die Liste (gleiche Überlegung wie bei den Aktionsmenüs, siehe positionFlyout in chrome.js). */
.filterTagFlyoutList {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
}

.filterTagFlyoutMode {
	display: flex;
	flex-direction: column;
	font-size: 0.85em;
	gap: 0.3rem;
}

/* "Alle"/"Keine" am Fuß der Mehrfachauswahl-Flyouts. Beide teilen sich die Panelbreite zu gleichen Teilen,
   damit sie als ein Paar auftreten; das margin der .miniBtn entfällt, den Abstand setzt hier das gap. */
.filterFlyoutBulkActions {
	display: flex;
	gap: 0.4rem;
}

.filterFlyoutBulkActions .miniBtn {
	flex: 1;
	margin: 0;
}

/* Flyouts, deren Einträge nur aus einem Wort bestehen (Sehstatus, Bewertung, ...), sollen nicht auf die für
   Tag- und Genre-Listen gedachte Mindestbreite aufgeblasen werden. */
.filterFlyoutPanelNarrow {
	min-width: 0;
}

/* Hält den Platz des Zustands-Symbols vor der Beschriftung frei, auch bei "alle", das keines trägt - sonst
   stünde dessen Text als einziger weiter links (siehe filter_icon_flyout). */
.filterOptionIcon {
	display: inline-flex;
	justify-content: center;
	width: 1.15em;
}

/* Der gewählte Wert neben dem Symbol des Auslösers (siehe filter_rating_flyout). Ohne :empty-Regel bliebe
   bei "alle" der Abstand des leeren Elements stehen und der Knopf wäre breiter als die übrigen. */
.filterFlyoutValue:empty {
	display: none;
}

input[type="text"],
input[type="password"],
input[type="search"],
input[type="date"],
input[type="time"],
input[type="number"],
select,
textarea {
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--field-radius);
	color: var(--control-text);
	font-size: 0.9rem;
	height: var(--control-height);
	line-height: 1rem;
	margin: 0;
	padding: 0 0.6rem;
}

/* Der Textbereich wächst mit seinem Inhalt, eine feste Höhe wäre hier falsch. font-family, weil Browser hier
   sonst als einzigem Formularelement eine Schreibmaschinenschrift einsetzen: */
textarea {
	font-family: inherit;
	height: auto;
	line-height: 1.4;
	padding: 0.4rem 0.6rem;
	resize: vertical;
}

/* Das Dateifeld bringt seine Schaltfläche selbst mit, vom Browser gezeichnet - ohne eigene Regeln steht sie als
   einziges Element in Systemoptik (hellgrauer Kasten) im Dialog. Das Feld selbst bleibt unsichtbar und trägt nur
   den Text daneben ("keine Datei ausgewählt"), die Schaltfläche bekommt die Pillenform.
   Die Beschriftung stellt der Browser in der Sprache des Systems, darauf haben wir keinen Zugriff. */
input[type="file"] {
	align-items: center;
	background-color: transparent;
	border: none;
	color: var(--text-muted);
	display: inline-flex;
	font-size: 0.9rem;
	gap: 0.6rem;
	height: auto;
	max-width: 100%;
	padding: 0;
}

input[type="file"]::file-selector-button {
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	cursor: pointer;
	font-family: inherit;
	font-size: 0.9rem;
	height: var(--control-height);
	padding: 0 0.9rem;
}

input[type="file"]::file-selector-button:active {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

/* Firefox */
input[type="number"] {
	appearance: textfield;
}
/* Chrome, Safari, Edge, Opera */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

/* Chrome, Safari, Edge, Opera: natives Suchfeld-Aussehen an die übrigen Eingabefelder angleichen */
input[type="search"] {
	-webkit-appearance: none;
	appearance: none;
}

/* Das Löschzeichen im Suchfeld selbst zeichnen. Chromium liefert dafür eine Grafik mit senkrechtem Farbverlauf: Auf
   unserem dunklen Untergrund verblasst deren untere Hälfte so weit, dass vom "x" nur die oberen Schenkel übrig
   bleiben - es liest sich als "v". Als Maske eingefärbt hat das Zeichen dagegen überall dieselbe Deckkraft.

   Die Maske kommt ohne "#" aus (Farbe als Wortname), weil ein Doppelkreuz in einer CSS-url() den Rest als Fragment
   abschneiden würde. Firefox zeigt an dieser Stelle ohnehin nichts an, dort bleibt die Regel wirkungslos. */
input[type="search"]::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
	background-color: var(--text-muted);
	cursor: pointer;
	height: 1em;
	-webkit-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 6 L18 18 M18 6 L6 18' stroke='black' stroke-width='2.5' stroke-linecap='round' fill='none'/></svg>") center / contain no-repeat;
	mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 6 L18 18 M18 6 L6 18' stroke='black' stroke-width='2.5' stroke-linecap='round' fill='none'/></svg>") center / contain no-repeat;
	width: 1em;
}

input[type="search"]::-webkit-search-cancel-button:hover {
	background-color: var(--text);
}

input[type="text"]:focus-visible,
input[type="password"]:focus-visible,
input[type="search"]:focus-visible,
input[type="date"]:focus-visible,
input[type="time"]:focus-visible,
input[type="number"]:focus-visible,
select:focus-visible,
textarea:focus-visible {
	border-color: var(--control-border-hover);
	outline: none;
}

table {
	border-collapse: collapse;
	border-color: var(--line-table);
	border-spacing: 0;
	text-align: left;
}

/* Der Tabellenkopf ist ein abgesetztes Band, wie die Kopfzeile eines Dialogs - deutlich genug, um die Spalten
   zu tragen, aber ohne den Zeilen darunter die Aufmerksamkeit zu nehmen. */
th {
	background: var(--table-header-bg);
	color: var(--table-header-text);
	font-size: 0.9rem;
	font-weight: bold;
	white-space: nowrap;
}

/* Die Zellenlinien tragen die Struktur der Tabelle - neutral statt blau, siehe --line-table. */
th, td {
	border-color: var(--line-table);
	padding: 3px 7px;
}

.defaultTable td {
	overflow-wrap: anywhere;
}

th .sortIcon {
	color: #ccc;
	margin-left: 0.25em;
}

th .sortIcon.sortIconOnly {
	margin-left: 0;
}

th a,
td.dir a {
	color: inherit;
	text-decoration: none;
}

.subTh {
	float: right;
	font-size: 0.75rem;
	font-weight: normal;
	line-height: 1rem;
	margin-left: 2em;
}

.dir .timerState2 {
	vertical-align: bottom;
}

.count,
.unwatched,
.size,
.length,
.modified,
.age,
.timerCount {
	text-align: right;
}

.title a {
	color: inherit;
	text-decoration: none;
}

.seasonEpisode {
	color: #68c;
}

.switchSender .senderName {
	color: #ccc;
	font-size: 0.75em;
	display: inline-block;
	margin-top: 0.2em;
	vertical-align: center;
}

.epgSelectBar {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 0.5em;
	margin: 1em 0;
}

.epgSelectBar #selectEpgBouquet,
.epgSelectBar #selectEpgService,
.epgSelectBar .switchSender,
.epgSelectBar #watchLiveBtn,
.epgSelectBar #watchLiveExternalBtn,
.epgSelectBar #epgSearchInput,
.epgSelectBar #epgSearchBtn,
.epgSelectBar #epgLeaveSearchBtn {
	height: var(--control-height);
	margin: 0;
}

.epgSelectBar #selectEpgBouquet,
.epgSelectBar #selectEpgService {
	line-height: 1.1em;
}

.epgSelectBar button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.epgSelectBar button i {
	padding: 0;
}

.desc,
.timeofday,
.timerEnd,
.epgEnd,
.repeatedInfo {
	color: #aaa;
	font-size: 0.75em;
}

.timerItem .time {
	vertical-align: top;
}
.epgTable .time {
	white-space: nowrap;
}
.timerItem .time .startTime,
.timerItem .time .stateInfo,
.timerItem .time .timerEnd,
.timerItem .time .repeatedInfo,
.epgItem .time .epgEnd {
	white-space: nowrap;
}

.timerItem .timerMeta,
.epgItem .epgMeta,
.epgItem .timerRange {
	font-size: 0.75rem;
	line-height: 1.2rem;
}
.timerItem .timerMeta .stateInfo,
.timerItem .timerMeta .timerEnd,
.epgItem .epgMeta .epgEnd {
	font-size: inherit;
}
.timerItem .timerMeta .timerEnd,
.epgItem .epgMeta .epgEnd {
	float: right;
}

.epgItem .timerRange.fullTimer.runningTimer {
	color: #6af;
}
.epgItem .timerRange.partialTimer.runningTimer {
	color: #68c;
}

.epgProgress .epgProgressBar,
.timerProgress .timerProgressBar {
	background-color: #68c;
	border-radius: 3px;
	height: 0.5em;
	margin: 0.2em 0;
}

.epgProgress .epgProgressBar {
	background-color: #aaa;
}

.playProgress {
	background-color: #666;
	border-radius: 3px;
	height: 0.5em;
	margin: 0.2em 0;
	position: relative;
	width: 100%;
}

.playProgress .playProgressBar {
	background-color: #aaa;
	border-radius: 3px;
	height: 0.5em;
	margin: 0.2em 0;
	position: relative;
	z-index: 1;
}

.playProgress .cutmark {
	background-color: #6af;
	border-radius: 1px;
	bottom: 0;
	pointer-events: none;
	position: absolute;
	top: 0;
	width: 1px;
	z-index: 2;
}

.playProgress .jumpmark {
	background-color: #b67b50;
	border-radius: 1px;
	bottom: 0;
	pointer-events: none;
	position: absolute;
	top: 0;
	width: 1px;
	z-index: 2;
}

.timerProgress,
.epgProgress {
	background-color: #346;
	border-radius: 3px;
	height: 0.5em;
	margin: 0.2em 0;
	width: 100%;
}

.epgProgress {
	background-color: #666;
}

.playNextEpisodeBtn {
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	font-weight: bold;
	margin: 0 0.25em 0 1em;
	padding: 0.2rem 0.7rem;
}

.playNextEpisodeBtn i {
	margin-right: 0.2em;
}

.playNextEpisodeDesc {
	color: #ccc;
	font-size: 0.75em;
}

.abandonedBookmarks {
	margin-bottom: 1rem;
}

.movieDirsTable .indent {
	color: #999;
	font-weight: bold;
}

.movieItem .title .isCutting,
.movieItem .title .isPlaying {
	display: block;
	float: right;
	margin: 0 0.25em 0 0.5em;
}

.movieItem .timerRunningInfo {
	display: flex;
	flex-direction: column;
	text-align: center;
}
.movieItem .timerRunningInfo .timerRunningIcon {
	display: block;
	font-size: 1.3em;
}

.movieItem .isCutting,
.movieItem .isPlaying {
	color: #6af;
	text-align: center;
}

.movieItem .isCutting .cuttingIcon,
.movieItem .isPlaying .playingIcon {
	display: block;
	font-size: 1.5em;
}
.movieItem .isPlaying .playingIcon {
	margin: 0 0.2em 0 0;
}

.movieItem .isCutting .cuttingText,
.movieItem .isPlaying .playingText {
	display: block;
	font-size: 0.75em;
}

.movieItem .type {
	text-align: center;
}

.movieItem .time {
	white-space: nowrap;
}

/* inline-flex, damit die Schaltfläche darin die Mitte der Zeile trifft: als Inline-Element richtete sie sich an
   der Schriftlinie aus und saß knapp 2px zu hoch. */
.autoTimerActions {
	align-items: center;
	display: inline-flex;
	position: relative;
}

.autoTimerActionFlyout {
	background-color: var(--surface);
	border: 1px solid var(--line);
	border-radius: 3px;
	color: #ddd;
	display: flex;
	flex-direction: column;
	left: 0;
	margin-top: 2px;
	opacity: 0;
	padding: 0;
	pointer-events: none;
	position: absolute;
	top: 100%;
	transition: opacity 0.3s ease;
	visibility: hidden;
	z-index: 20;
}

.autoTimerActionFlyout.open {
	opacity: 1;
	pointer-events: auto;
	visibility: visible;
}

.autoTimerActionFlyout .autoTimerAction {
	color: #ddd;
	cursor: pointer;
	padding: 0.5em 1em 0.5em 0.75em;
	white-space: nowrap;
}

.autoTimerActionFlyout .autoTimerAction i {
	margin-right: 0.5em;
}

.autoTimerActionFlyout .autoTimerAction:active {
	background-color: rgba(102, 153, 221, 0.2);
	color: #fff;
}

.timerItem .stateIcon,
.timerItem .testState,
.timerItem .box,
.timerItem .type,
.autoTimerItem .stateIcon,
.autoTimerItem .box,
.autoTimerItem .type,
.epgTable .timer {
	text-align: center;
	vertical-align: middle;
}

.autoTimerItem .meta {
	white-space: nowrap;
}
.autoTimerItem .meta i {
	color: #aaa;
}

.autoTimerItem:not(.autoTimerDisabled) .meta .timeRange,
.autoTimerItem:not(.autoTimerDisabled) .meta .timeRange i,
.autoTimerItem:not(.autoTimerDisabled) .meta .dateRange,
.autoTimerItem:not(.autoTimerDisabled) .meta .dateRange i,
.autoTimerItem:not(.autoTimerDisabled) .meta .weekdays,
.autoTimerItem:not(.autoTimerDisabled) .meta .weekdays i {
	color: #6af;
}

.autoTimerItem .filter {
	text-align: right;
}

.autoTimerItem .sender a {
	color: #ddd;
}

.autoTimerItem .more {
	color: #aaa;
	font-style: italic;
}

.autoTimerItem .sender hr {
	border: none;
	border-top: 1px dashed #999;
	margin: 0.5em 0;
}

.timerItem[data-state="3"] .title,
.timerItem[data-state="3"] .seasonEpisode,
.timerItem[data-state="3"] .time,
.timerItem[data-state="3"] .length,
.timerItem[data-state="3"] .type,
.timerItem[data-state="3"] .sender,
.timerItem[data-state="3"] .autoTimer,
.timerItem[data-state="3"] .tags,
.timerItem[data-state="3"] a,
.autoTimerItem.autoTimerDisabled > :not(.actions),
.autoTimerItem.autoTimerDisabled a,
.epgItem .partialTimer {
	color: #aaa;
}

.timerItem .cryptIcon {
	color: #999;
}

.timerState0,
.timerState0 .iconBtn {
	color: #fff;
}
.timerState1,
.timerState1 .iconBtn {
	color: #cc0;
}
.timerState2,
.timerState2 .iconBtn {
	color: #6af;
}
.timerState3,
.timerState3 .iconBtn {
	color: #0e0;
}
.timerDisabled,
.timerDisabled .iconBtn,
.stateIcon.autoTimerDisabled,
.stateIcon.autoTimerDisabled i {
	color: #e00;
}

.movieItem .stateInfo,
.timerItem .stateInfo {
	font-size: 0.75em;
}

.stateInfo .timerState1,
.stateInfo.timerState1 {
	color: #cc0;
}
.stateInfo .timerState2,
.stateInfo.timerState2 {
	color: #6af;
}
.stateInfo .timerState3,
.stateInfo.timerState3 {
	color: #0c0;
}
.stateInfo .timerDisabled,
.stateInfo.timerDisabled {
	color: #c00;
}

.overlaps {
	color: #cc0;
}

.timerMeta .overlaps {
	float: right;
	margin-right: 0.5em;
}

.movieDirItem .count,
.movieDirItem .unwatched,
.movieDirItem .size,
.movieDirItem .length,
.movieDirItem .modified,
.movieDirItem .age,
.movieItem .sender,
.movieItem .tags,
.timerItem .testMsg,
.timerItem .sender,
.timerItem .tags,
.timerItem .autoTimer,
.autoTimerItem .meta,
.autoTimerItem .sender,
.autoTimerItem .bouquets,
.autoTimerItem .tags {
	font-size: 0.75em;
}

.timerItem.skip * {
	color: #999;
}

.actions {
	white-space: nowrap;
}

.actions .actionWrapper {
	position: relative;
}

.actions .toggleActionFlyout {
	display: none;
}

.actions .actionFlyout {
	display: flex;
	flex-direction: row;
	gap: 0.25em;
	padding: 0.25em 0;
}

.actions.actionsSmall .actionFlyout {
	padding-bottom: 0;
	padding-top: 0;
}

/* Die Haupt-Buttons tragen dieselbe Beschriftung wie die Einträge des "Mehr"-Menüs, sichtbar wird sie aber erst
   auf schmalen Bildschirmen: dort verschmelzen beide Bereiche zu einem einzigen senkrechten Menü (siehe
   @media max-width:1024px). In der Zeile stehen sie als reine Icons, ihre Bedeutung nennt der title-Tooltip.
   Kindselektor, damit die Einträge des eingebetteten .moreFlyout ihre Beschriftung behalten. */
.actions .actionFlyout > button > span,
.actions .actionFlyout > a > span {
	display: none;
}

.actions button {
	background-color: transparent;
	border: none;
	color: white;
	cursor: pointer;
	padding: 0.25rem 0.25rem;
}

.actions.actionsSmall button {
	padding: 0.1rem 0.1rem;
}

th.actions > button,
th.actions .actionWrapper > button {
	padding-bottom: 0;
	padding-top: 0;
}

.actions button i {
	font-size: 1.2rem;
}

button[disabled] i,
.actions button[disabled] i {
	color: #999;
}

/* Schriftfarbe mit abdunkeln, nicht nur das Icon (siehe Regel darüber): sonst steht ein graues Icon neben
   hellem Text und der Button wirkt halb deaktiviert. Entspricht dem Vorgehen bei .defaultCheckboxLabel. */
button[disabled],
.actions button[disabled] {
	color: #999;
	cursor: not-allowed;
}

/* "Mehr"-Menü (vertikales Popup für seltener genutzte Action-Buttons) -------------------------- */

/* z-index 8 hält das Menü unter der Kopfzeile (z-index 10). Es hängt per position:absolute an seinem Button und
   wandert beim Scrollen mit; ohne den niedrigeren Wert schöbe es sich über die Kopfzeile, denn bei gleichem
   z-index gewinnt das im Dokument spätere Element. So verschwindet es beim Hochscrollen sauber dahinter.
   Die beiden Flyouts der Kopfzeile selbst sind davon nicht betroffen: sie liegen innerhalb deren Stapelkontext
   und stehen damit trotz der 8 über dem Seiteninhalt. */
.actions .moreFlyout {
	background-color: var(--surface-raised);
	border: 1px solid var(--control-border);
	border-radius: 10px;
	color: var(--control-text);
	display: none;
	flex-direction: column;
	gap: 0.1em;
	margin-top: 2px;
	padding: 0.4em;
	position: absolute;
	right: 0;
	top: 100%;
	z-index: 8;
}

.actions .moreFlyout.open {
	display: flex;
}

.actions .moreFlyout button,
.actions .moreFlyout a {
	align-items: center;
	color: white;
	display: flex;
	gap: 0.6em;
	justify-content: flex-start;
	padding: 0.4em 0.75em;
	text-align: left;
	text-decoration: none;
	white-space: nowrap;
	width: 100%;
}

.actions .moreFlyout button:active:not([disabled]),
.actions .moreFlyout a:active {
	background-color: rgba(102, 153, 221, 0.2);
	border-radius: 6px;
	color: #fff;
}

.actions .moreFlyout button span,
.actions .moreFlyout a span {
	font-size: 0.85rem;
}

/* Gruppentrenner innerhalb eines "Mehr"-Menüs (Abspielen/Bearbeiten/Suchen ...). Dieselbe Linie wie zwischen Haupt-
   und "Mehr"-Bereich des zusammengelegten Menüs schmaler Bildschirme, damit im selben Menü nicht zwei verschiedene
   Trenner stehen. Ein eigenes Element statt border-top am ersten Eintrag einer Gruppe: Welcher Eintrag das ist,
   hängt an {% if %}-Bedingungen und wäre im Template nicht verlässlich zu treffen. */
.actions .moreFlyout .moreFlyoutSeparator {
	border-top: 1px solid var(--control-border);
	margin: 0.3em 0;
}

.actions .moreFlyout button[disabled] span {
	color: #999;
}

/* Sortierung: Pille mit Kriteriums- und Richtungssymbol (siehe inc/tools.html#sort_flyout) -------- */

/* Die Höhe steht fest statt aus der line-height zu entstehen, damit die Pille exakt so hoch ist wie die
   Elemente daneben (dieselbe Begründung wie bei .defaultBtn) - auf den TMDB-Seiten steht sie inzwischen in
   der Filterleiste statt in der Kopfzeile, wo dieselbe --control-height gilt. Der Selektor ist bewusst
   spezifischer als ".actions button" (transparent, randlos), das ihr sonst die Fläche nähme. */
.actions .sortPill {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	display: inline-flex;
	gap: 0.1em;
	height: var(--control-height);
	justify-content: center;
	padding: 0 0.6em;
}

.actions .sortPill:active {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

/* Das Richtungssymbol tritt gegenüber dem Kriterium zurück - es beantwortet nur die Nebenfrage. */
.actions .sortPill .sortPillDir {
	font-size: 0.9rem;
	opacity: 0.75;
}

/* Der eingestellte Eintrag bleibt im Menü sichtbar markiert, damit die zwei Symbole der Pille nicht die
   einzige Auskunft darüber sind, wonach gerade sortiert wird. */
.actions .moreFlyout .sortOption.active {
	background-color: var(--control-bg-hover);
	border-radius: 6px;
	color: var(--control-text-hover);
}

.actions .moreFlyout .sortOption.active span {
	font-weight: bold;
}

/* .actionWrapper steht beim Tonspur-Flyout in der Info-Box der Startseite (anders als sonst in einer Tabellenzelle
   oder einem Flex-Container) im Fließtext der "Läuft"-Überschrift. Als Block-Element würde es dort einen
   Zeilenumbruch erzwingen und das Icon unter statt neben den Text legen. inline-block hält es in der Zeile,
   position:relative bleibt für das absolut positionierte .moreFlyout erhalten (siehe .actions .actionWrapper).
   Am zweiten Einsatzort, der Kopfzeile, gilt das nicht - dort steht der Wrapper in einem Flex-Container und
   .globalActions .actions .actionWrapper überschreibt das inline-block wieder.
   vertical-align: bottom, weil .db-headline .iconBtn direkte Geschwister (z.B. den Info-Button) so ausrichtet -
   ohne das hier zu wiederholen, würde der Wrapper stattdessen sein eigenes Standard-"baseline" nutzen und
   dadurch höher sitzen als ein Button, der direkt (ohne Wrapper) in derselben Zeile steht. */
.audioTrackActions .actionWrapper {
	display: inline-block;
	vertical-align: bottom;
}

/* Der Tonspur-Auslöser ist zwar ein .iconBtn wie seine Nachbarn, steht aber zusätzlich in .actions - und
   ".actions button" (eine Klasse + ein Typ) ist spezifischer als ".iconBtn" und überschreibt dessen Maße. Beides
   hier zurückholen, sonst säße das Icon größer und um die 0.25rem Innenabstand nach oben versetzt daneben.
   Bei der Größe bewusst "inherit" statt eines festen Werts: die beiden Einsatzorte geben ihren Icons
   unterschiedliche Maße vor (1rem in der Info-Box via .content .db-info .db-headline .iconBtn, in der Kopfzeile
   2.5em via .globalActions). Bewusst nur der Auslöser und nicht ".audioTrackActions .iconBtn": das träfe auch die
   Schaltflächen im Flyout, die ihre Maße weiter unten selbst regeln. */
.audioTrackActions .toggleMoreFlyout {
	padding: 0 5px;
}

.audioTrackActions .toggleMoreFlyout i {
	font-size: inherit;
}

/* Tonspur-Flyout (siehe inc/audioTrackFlyout.html): bei einer laufenden Aufnahme trägt eine Zeile zwei
   Schaltflächen (umschalten, umschalten+zurückspulen) statt einer - die Buttonbreite 100% von .moreFlyout
   button passt dafür nicht, hier stehen sie stattdessen nebeneinander in einer flexiblen Zeile. */
/* Der "Läuft"-Kopf der Info-Box (.db-headline) schreibt Großschreibung und weite Laufweite für sich selbst vor -
   beides hier zurücknehmen, sonst erben es die Tonspurnamen mit. (Schaltflächen sind von text-transform nicht
   betroffen: Buttons setzen es kraft User-Agent-Stylesheet ohnehin zurück.) line-height ebenso auf normal, damit
   das Flyout unabhängig davon bleibt, was sein jeweiliger Einsatzort für seine eigene Zeile vorgibt. */
.audioTrackFlyout {
	letter-spacing: normal;
	line-height: normal;
	text-transform: none;
}

/* gap etwas weiter als die 0.2em von früher: der Kreis rechts (s.u.) braucht Luft zur Zeile, sonst berührt
   seine Umrandung fast den Tonspurnamen. */
.audioTrackFlyout .audioTrackRow {
	align-items: center;
	display: flex;
	gap: 0.4em;
}

.audioTrackFlyout .audioTrackRow button {
	flex: 1;
	width: auto;
}

.audioTrackFlyout .audioTrackRow button[data-rc] {
	flex: none;
}

/* Die Zeile ist als Ganzes klickbar (Tonspur umschalten) und trägt rechts eine zweite, eigenständige
   Schaltfläche (umschalten und dabei zurückspulen). Ohne eigene Fläche verschmilzt die mit der Zeile und liest
   sich wie deren Beschriftung. Sie ist eine reine Icon-Schaltfläche und bekommt deshalb den Kreis der
   Formensprache (siehe :root); die kleine Höhe und die ruhige Grundfarbe halten sie als Zweitaktion hinter der
   Zeile zurück, die ja die häufigere Handlung trägt. Der Ruhezustand muss die Klickbarkeit allein zeigen -
   bedient wird per Touch, und Hover-Effekte gibt es in dieser Anwendung ohnehin nicht. */
.audioTrackFlyout .audioTrackRow .iconBtn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: 50%;
	color: var(--control-text);
	display: inline-flex;
	height: var(--control-height-small);
	justify-content: center;
	padding: 0;
	width: var(--control-height-small);
}

/* Im Kreis bezieht sich das Icon auf dessen Fläche, nicht mehr auf die bloßen Icons der Zeile - mit den 1.2rem
   aus ".actions button i" bliebe kaum Luft zum Rand. */
.audioTrackFlyout .audioTrackRow .iconBtn i {
	font-size: 1rem;
}

.audioTrackFlyout .audioTrackRow .iconBtn:active {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

/* font-size explizit wie .moreFlyout button span (dort per Nachfahren-Selektor gesetzt, hier ohne Button
   nicht getroffen) - sonst erbt die aktive Zeile die viel größere Schrift des "Läuft"-Kopfs und sticht
   trotz gleicher Zeilenhöhe wie die anderen Einträge unpassend heraus. */
.audioTrackFlyout .audioTrackName {
	align-items: center;
	color: #fff;
	display: flex;
	font-size: 0.85rem;
	gap: 0.6em;
	padding: 0.4em 0.75em;
	white-space: nowrap;
}

/* Icon so groß wie in den Schaltflächen der übrigen Zeilen (.actions button i). Ohne das erbt es die 0.85rem
   der Regel darüber und wäre als einziges kleiner - und weil die Icons die Tonspurnamen nach rechts schieben,
   stünde zugleich der aktive Name weiter links als die anderen. */
.audioTrackFlyout .audioTrackName i {
	font-size: 1.2rem;
}

/* Der Umschalter zeigt immer nur den einen sinnvollen Eintrag: bei einer gesehenen Aufnahme "als ungesehen markieren"
   und umgekehrt (siehe movielist.html).

   Die vier Klassen sind Absicht und dürfen nicht auf ".movieItem[data-watched] .setWatched" zusammengestrichen werden:
   Auf schmalen Bildschirmen werden die Knöpfe zu Menüeinträgen, und die Regel dafür
   (".actions .actionFlyout > button:not(.toggleMoreFlyout)", siehe unten im @media-Block) läge mit ihren drei Klassen
   sonst darüber - dann stünden beide Einträge gleichzeitig im Menü. */
.movieItem[data-watched="true"] .actionFlyout > .setWatched,
.movieItem[data-watched="false"] .actionFlyout > .setUnwatched {
	display: none;
}

/* Der Knopf trägt zwei Symbole: eines für den Zustand und eines für die Aktion (siehe movielist.html). Ohne
   Beschriftung gilt der Zustand; das Gegenstück blendet der @media-Block für schmale Bildschirme ein, wo die Aktion
   als Text daneben steht. */
.watchedIconAction {
	display: none;
}

.toggleBookmark .bookmarkIconActive,
.toggleBookmark .bookmarkIconInactive {
	display: none;
}
.toggleBookmark.active .bookmarkIconActive,
.toggleBookmark:not(.active) .bookmarkIconInactive {
	display: inline;
}

.addToLists .addToListsIconActive,
.addToLists .addToListsIconInactive {
	display: none;
}
.addToLists.active .addToListsIconActive,
.addToLists:not(.active) .addToListsIconInactive {
	display: inline;
}

/* Serien-Verknüpfen-Button neben der Breadcrumb (siehe movielist.html) - dieselbe Farbe wie .tmdbGotoSeries im
   Action-Menü der Zeilen, hier aber gegen .infoBar .iconBtn (color: var(--control-text)) durchgesetzt: */
.infoBar .iconBtn.tmdbGotoSeries {
	color: #6af;
}

.iconBtn {
	background-color: transparent;
	border: none;
	color: white;
	cursor: pointer;
	padding: 0 5px;
}

/* In den Kopf- und Filterleisten stehen die Icon-Schaltflächen zwischen anderen Bedienelementen und werden
   deshalb wie diese gestaltet: rund, in derselben Höhe. Bewusst nur dort - in der Seiten-Kopfzeile und im
   Dialog-Kopf ist .iconBtn Teil der Chrome (Ein/Aus, Lautstärke, Schließen) und soll keine Fläche bekommen. */
.infoBar .iconBtn,
.filterBar .iconBtn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: 50%;
	color: var(--control-text);
	display: inline-flex;
	height: var(--control-height);
	justify-content: center;
	padding: 0;
	width: var(--control-height);
}

.infoBar .iconBtn:active,
.filterBar .iconBtn:active,
/* Aufgeklappte Filterleiste: derselbe Zustand wie bei .seg-btn.active und .tmdbIconBtn.active. */
.infoBar .filterToggleBtn.active {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

/* Der Standardabstand der Schaltflächen stammt aus dem Textfluss und stört in diesen Leisten: sie sind
   Flex-Zeilen und regeln den Abstand über gap. Schlimmer noch, bei align-items:center wird die Margin-Box
   zentriert - ein Abstand nur unten hob die Schaltfläche um die Hälfte davon aus der Zeilenmitte. */
.infoBar .defaultBtn,
.infoBar .smallBtn,
.infoBar .miniBtn,
.filterBar .defaultBtn,
.filterBar .smallBtn,
.filterBar .miniBtn {
	margin: 0;
}

/* Schaltfläche mit Beschriftung: Pille. Die Höhe steht fest, statt aus der line-height zu entstehen - sonst
   stünde eine Schaltfläche, die nur ein Icon enthält, rund 9px flacher als die Beschriftete daneben. */
.defaultBtn,
.smallBtn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-family: inherit;
	font-size: 0.9rem;
	gap: 0.35rem;
	height: var(--control-height);
	justify-content: center;
	margin: 0 0.5em 0.25em 0;
	padding: 0 0.9rem;
	text-decoration: none;
}

.smallBtn {
	white-space: nowrap;
}

.defaultBtn i,
.smallBtn i {
	font-size: 1.1rem;
}

/* Kompakte Variante für dichte Zeilen (Filterleiste, Tabellenkopf): dieselbe Form, eine Nummer kleiner. */
.miniBtn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-family: inherit;
	font-size: 0.85rem;
	gap: 0.3rem;
	height: var(--control-height-small);
	justify-content: center;
	margin: 0 0 0.25em 0;
	padding: 0 0.7rem;
	vertical-align: middle;
}

.defaultBtn:active:not([disabled]),
.smallBtn:active:not([disabled]),
.miniBtn:active:not([disabled]) {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

.defaultBtn[disabled],
.smallBtn[disabled],
.miniBtn[disabled] {
	background-color: var(--control-bg-disabled);
	border-color: var(--control-border-disabled);
	color: var(--control-text-disabled);
}

.defaultBtn:focus-visible,
.smallBtn:focus-visible,
.miniBtn:focus-visible {
	border-color: var(--control-border-hover);
	outline: none;
}

/* Schaltfläche ohne Beschriftung: rund und so breit wie hoch - dieselbe Form wie die "..."-Menüs und die
   Zurück-/Blätter-Buttons. Die Breite folgt der Höhe der jeweils mitgegebenen Größe, .iconOnlyBtn wird sowohl
   mit .smallBtn als auch mit .miniBtn kombiniert (siehe epg.html bzw. autotimer.html). */
.iconOnlyBtn {
	border-radius: 50%;
	min-width: auto;
	padding: 0;
}

.defaultBtn.iconOnlyBtn,
.smallBtn.iconOnlyBtn {
	width: var(--control-height);
}

.miniBtn.iconOnlyBtn {
	width: var(--control-height-small);
}

.iconOnlyBtn i {
	display: block;
	margin: 0;
}

.defaultCheckbox {
	display: none;
}

/* Beschriftetes Kästchen als Pille - es verhält sich wie eine Schaltfläche zum Ein-/Ausschalten. */
.defaultCheckboxLabel {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-size: 0.9em;
	gap: 0.4em;
	line-height: 1em;
	padding: 0.35em 0.8em;
}

.defaultCheckboxLabel:active {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

.defaultCheckbox:disabled + .defaultCheckboxLabel {
	color: #999;
	cursor: not-allowed;
}

/* flex-shrink: 0 ist zwingend: das Label ist inline-flex, der Marker also ein Flex-Item. Ohne die Regel wird
   er zusammengedrückt, sobald der Text umbricht (schmales Display, langer Text) - der Marker ist dann schmaler
   als hoch und der Text rutscht nach links. Gleiches gilt für .defaultRadioLabel::before: */
.defaultCheckboxLabel::before {
	background-color: var(--page-bg);
	border: 1px solid var(--control-border);
	border-radius: 4px;
	content: "";
	display: inline-block;
	flex-shrink: 0;
	height: 1em;
	line-height: 1em;
	margin-right: 0.6em;
	width: 1em;
}

.defaultCheckbox:checked + .defaultCheckboxLabel::before {
	background-color: var(--control-border);
	border: 1px solid var(--control-border);
	border-radius: 4px;
	content: "✓";
	color: #fff;
	display: inline-flex;
	font-weight: bold;
	text-align: center;
}

.defaultCheckbox-x:checked + .defaultCheckboxLabel::before {
	content: "✘︎";
}

/* Radiobutton-Pendant zu .defaultCheckbox: gleiches Muster (verstecktes Input + Label mit
   gezeichnetem Marker), nur rund statt eckig und ohne Häkchen. */
.defaultRadio {
	display: none;
}

.defaultRadioLabel {
	align-items: center;
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-size: 1em;
	gap: 0.4em;
	line-height: 1em;
}

.defaultRadio:disabled + .defaultRadioLabel {
	color: #999;
	cursor: not-allowed;
}

.defaultRadioLabel::before {
	background-clip: content-box;
	background-color: transparent;
	border: 1px solid var(--control-border);
	border-radius: 50%;
	box-sizing: border-box;
	content: "";
	display: inline-block;
	flex-shrink: 0;
	height: 1em;
	line-height: 1em;
	margin-right: 0.6em;
	padding: 2px;
	width: 1em;
}

/* background-clip: content-box sorgt dafür, dass die Füllung innerhalb des Rahmens bleibt (Punkt in
   der Mitte statt Fläche bis zum Rand) - der Rahmen bleibt so auch im ausgewählten Zustand sichtbar.
   Der Punkt ist bewusst hell und nicht in der Rahmenfarbe: er ist die Markierung, wie das Häkchen bei
   .defaultCheckbox, und muss sich vom Rahmen absetzen. */
.defaultRadio:checked + .defaultRadioLabel::before {
	background-color: var(--text);
}

.editItem.active {
	background-color: var(--control-bg);
}

/* Edit-Form ------------------------------------------------------------------------------------ */

.editForm {
	background-color: var(--surface);
	border: 1px solid var(--line);
	border-radius: 5px;
	height: fit-content;
	margin: 1em 0 0 0;
	max-height: calc(100dvh - 6em);
	max-width: 29em;
	overflow-y: auto;
	padding: 1em 0.5em 1em 1em;
	position: sticky;
	scrollbar-gutter: stable;
	top: 5em;
}

/*.editMovieForm {
	min-width: 30em;
}

.editTimerForm {
	min-width: 30em;
}*/

/* Knapp gehaltener Zeilenabstand: die Bedienelemente sind mit der Pillenform höher geworden, das Formular soll
   aber weiterhin ohne senkrechtes Scrollen auf ein Tablet passen. */
.editForm .form-group {
	margin-bottom: 1.1em;
	min-height: 1.5em;
	overflow: hidden;
}

.editForm > .form-group:last-child {
	margin-bottom: 0;
}

.editForm #prevEditBtn,
.editForm #nextEditBtn,
.editForm #closeEditBtn {
	font-size: 1.2em;
	position: absolute;
	top: 0.5em;
}
.editForm #prevEditBtn {
	right: 3.75em;
}
.editForm #nextEditBtn {
	right: 2em;
}
.editForm #closeEditBtn {
	right: 0.25em;
}

.editForm button[disabled] i {
	color: #999;
}

.editForm .fieldLabel {
	display: block;
	font-weight: bold;
	margin-bottom: 0.3em;
}

.editForm .fieldLabelIcon {
	color: #aaa;
	display: inline-block;
}

.editForm .fieldLabel #tagManageBtn {
	margin-left: 0.4em;
}

.editForm .fieldLabel .fieldLabelIcon {
	font-size: 0.8em;
	margin-left: 0.2em;
}

.editForm input[type="text"],
.editForm textarea {
	width: 100%;
}

.editForm input[type="date"],
.editForm input[type="time"] {
	width: min-content;
}

.editForm input[type="number"] {
	field-sizing: content;
	min-width: 3ch;
}

.editForm .checkbox-group,
.editForm .radio-group {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.hiddenCheckbox,
.hiddenRadio,
.editForm .checkbox-group input[type="checkbox"],
.editForm .radio-group input[type="radio"] {
	display: none;
}

/* Auswahl über verstecktes Input plus beschriftetes Label - die Labels verhalten sich wie kleine Schaltflächen
   und folgen deshalb deren Formensprache; das gewählte Label ist ausgefüllt wie ein aktives Segment. */
.hiddenCheckbox + label,
.hiddenRadio + label,
.editForm .checkbox-group label,
.editForm .radio-group label {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-size: 0.9em;
	gap: 0.3rem;
	margin: 0;
	padding: 0.2rem 0.7rem;
}

.hiddenCheckbox + label:active,
.hiddenRadio + label:active,
.editForm .checkbox-group label:active,
.editForm .radio-group label:active {
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

.hiddenCheckbox:checked + label,
.hiddenRadio:checked + label,
.editForm .checkbox-group input[type="checkbox"]:checked + label,
.editForm .radio-group input[type="radio"]:checked + label {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
	font-weight: bold;
}

.editForm .radio-group #editDisabled1:checked + label {
	background-color: #c33;
	border-color: #e55;
}

.editForm #showLongDesc {
	font-family: monospace;
	font-size: 1.2em;
	margin: 0;
}

.editForm .form-actions,
.editForm .form-field {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 0.5em;
}

.editForm .form-field span {
	line-height: 1.5rem;
}
.editForm .form-field .inputDesc {
	line-height: 1.7rem;
}

.editForm .form-field--nowrap {
	flex-wrap: nowrap;
}

.editForm .form-field--vertical {
	flex-direction: column;
}

.editForm .form-field + .form-field {
	margin-top: 0.5em;
}

.editForm .form-actions button {
	flex: auto 1;
	margin: 0;
}
.editForm .form-actions-equal-buttons button {
	flex: 1;
	margin: 0;
}

/* In .form-field sollen input/textarea so breit wie möglich sein, .btn soll rechts daneben nur so breit wie nötig sein */
.editMovieForm .form-field input[type="text"],
.editMovieForm .form-field textarea {
	flex: 1 1 auto;
}

/* In .form-field sollen input/textarea so breit wie möglich sein, .btn soll rechts daneben nur so breit wie nötig sein */
.editMovieForm .form-field .editFileExt,
.editMovieForm .form-field .btn {
	flex: 0 1 auto;
	line-height: 1.7rem;
	margin: 0;
}

.editForm .more,
#editLocationEmptyInfo {
	color: #aaa;
	font-style: italic;
}

#editTextFiltersInfo label {
	font-weight: bold;
}

.movieListTable.editing .length,
.movieListTable.editing .type,
.movieListTable.editing .size,
.movieListTable.editing .time,
.movieListTable.editing .sender,
.movieListTable.editing .tags,
.timerTable.editing .time,
.timerTable.editing .length,
.timerTable.editing .type,
.timerTable.editing .sender,
.timerTable.editing .tags,
.timerTable.editing .autoTimer,
.autoTimerTable.editing .type,
.autoTimerTable.editing .meta,
.autoTimerTable.editing .filter,
.autoTimerTable.editing .sender,
.autoTimerTable.editing .tags,
.autoTimerTable.editing .timerCount {
	display: none;
}

#selectServiceBtn,
#selectBookmarkLocationBtn {
	margin-left: 0.5rem;
}

.toggleFormGroup {
	color: #aaa;
	cursor: pointer;
}
.toggleFormGroup::before {
	content: "▶ ";
	line-height: 1.2em;
}
.toggleFormGroup.open::before {
	content: "▼ ";
}

/* Einstellungen -------------------------------------------------------------------------------- */

/* Menü links, gewählter Bereich rechts - und bewusst ohne die Kachel-/Kasten-Optik des übrigen Programms.
   Bis zum 03.09.2026 standen alle Bereiche als Stapel von .db-info-Kästen untereinander. Das skalierte nicht:
   Jeder neue Bereich machte die Seite unübersichtlicher, und in den schmalen Kästen kämpften Formulare und
   Tabellen ständig um Platz (zuletzt zwang die Boxen-Tabelle auf dem Tablet einen waagerechten Scrollbalken).
   Kästen sind für eine Übersicht gedacht, auf der alles gleichzeitig sichtbar sein soll - eine Einstellungsseite
   ist das Gegenteil davon. */
.settingsLayout {
	align-items: flex-start;
	display: flex;
	gap: 1.5rem;
}

.settingsNav {
	display: flex;
	flex: 0 0 13rem;
	flex-direction: column;
	gap: 0.2rem;
}

.settingsNavItem {
	align-items: center;
	border-radius: var(--field-radius);
	color: var(--control-text);
	display: flex;
	gap: 0.6rem;
	padding: 0.5rem 0.8rem;
	text-decoration: none;
}

/* Der gewählte Bereich trägt dieselbe Hervorhebung wie überall ein gewähltes Segment (siehe --control-bg-hover). */
.settingsNavItem.active {
	background: var(--control-bg-hover);
	color: var(--control-text-hover);
}

/* min-width: 0, damit eine breite Tabelle die Spalte nicht aufbläht, sondern in ihrem eigenen Rahmen scrollt
   (siehe .settingsTableWrap) - ein Flex-Kind schrumpft sonst nie unter seine Inhaltsbreite.
   Die Obergrenze deckelt die Zeilenlänge: Ohne sie lief die Trennlinie unter der Bereichsüberschrift bei 1500px
   Fensterbreite 1150px weit über ein Formular von 26rem - die Überschrift gehörte dann sichtbar zu nichts mehr.
   Sie muss aber die vier Spalten der Tabellen fassen (siehe .settingsTable td:has(input)), deshalb so großzügig. */
.settingsPanels {
	flex: 1 1 auto;
	max-width: 62rem;
	min-width: 0;
}

.settingsPanel {
	display: none;
}

.settingsPanel.active {
	display: block;
}

/* Dieselbe Form wie die Kopfzeile eines Kastens (siehe .content .db-info .db-headline): Die Seite verlässt zwar
   die Kachel-Optik, soll aber nicht aus der Formensprache fallen. */
.settingsPanelTitle {
	align-items: center;
	border-bottom: 2px solid var(--line);
	color: #fff;
	display: flex;
	font-size: 1.1rem;
	font-weight: bold;
	gap: 0.4rem;
	letter-spacing: 0.2em;
	margin: 0 0 0.8rem 0;
	padding-bottom: 0.4rem;
	text-transform: uppercase;
}

/* Abschließende Angabe unter einer Tabelle - etwas Luft nach oben, damit sie nicht an der letzten Zeile klebt. */
.settingsPanelFooter {
	margin-top: 1rem;
}

/* Der negative obere Abstand von .settingsHint ist dafür gedacht, den Text dicht unter ein Eingabefeld zu ziehen.
   Hier steht darüber aber eine Textzeile, und dort klebte er daran. */
.settingsPanelFooter + .settingsHint {
	margin-top: 0.4rem;
}

/* Einleitender Satz unter der Bereichsüberschrift - erklärt, was der Bereich überhaupt einstellt. Braucht mehr
   Luft nach unten als ein Hinweis unter einem Feld, weil eine Tabelle folgt. */
.settingsPanelIntro {
	margin: 0 0 1rem 0;
	max-width: 46rem;
}

/* Nur auf schmalen Bildschirmen sichtbar (siehe die Media Query am Ende dieses Blocks): Dort ersetzt der
   gewählte Bereich das Menü, und ohne diesen Knopf käme man nur über die Zurück-Taste des Browsers zurück.
   Bewusst ein nacktes Chevron und kein .iconBtn: Der runde Knopf wöge in einer Überschrift zu schwer. */
.settingsBack {
	background: none;
	border: none;
	color: var(--control-text);
	cursor: pointer;
	display: none;
	font-size: 1.1rem;
	letter-spacing: normal;
	line-height: 1;
	padding: 0.2rem 0.3rem 0.2rem 0;
}

.settingsSubheadline {
	color: #ddd;
	font-size: 1rem;
	margin: 1.5rem 0 0 0;
}

.settingsRows {
	display: grid;
	gap: 0.5rem;
}

/* Anders als .content .db-row bewusst ohne space-between: Im schmalen Kasten standen Beschriftung und Wert an
   dessen beiden Kanten, hier ist der Bereich so breit, dass sie dann nichts mehr miteinander zu tun hätten. */
.settingsRow {
	display: flex;
	font-size: 0.9rem;
	gap: 0.5rem;
}

.settingsValue {
	color: #6af;
	font-weight: bold;
}

/* Beschriftung über dem Feld statt daneben, und eine Obergrenze für die Breite: Die Eingaben hier sind kurz,
   ein Passwortfeld über die volle Bereichsbreite sähe nach Versehen aus. */
.settingsForm {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	margin-top: 0.5rem;
	max-width: 26rem;
}

/* Beschriftungen in der normalen Textfarbe, nicht gedämpft: Auf einer Einstellungsseite steht viel kurzer Text,
   und in --text-muted sahen Beschriftung und Erläuterung gleich aus, obwohl das eine zum Feld darunter gehört und
   das andere nur dabeisteht. Die Erläuterungen (.settingsHint) bleiben deshalb gedämpft - der Unterschied trägt
   jetzt die Gliederung. */
.settingsForm label {
	color: var(--text);
	font-size: 0.85rem;
}

.settingsForm input,
.settingsForm select {
	margin-bottom: 0.6rem;
	width: 100%;
}

.settingsForm .defaultBtn {
	align-self: flex-start;
}

/* Auf schmalen Bildschirmen passen die Spalten nicht nebeneinander, und eine Tabelle schrumpft nicht unter ihren
   Inhalt - ohne diesen Rahmen ragte sie über die Kante hinaus und die Aktionssymbole standen sichtbar außerhalb
   (gemessen: 8px über den Rand, bei 390px Fensterbreite).
   Der Rahmen fängt das ab und macht daraus waagerechtes Scrollen. Auf breiten Bildschirmen ändert sich nichts:
   overflow-x: auto zeigt den Balken nur, wenn es tatsächlich etwas zu scrollen gibt. */
.settingsTableWrap {
	max-width: 100%;
	overflow-x: auto;
}

.settingsTable {
	margin-top: 0.5rem;
	width: 100%;
}

/* Mehr Luft als die globalen 3px (siehe "th, td"): Jene sind auf dichte Listen mit hunderten Zeilen ausgelegt,
   hier stehen Eingabefelder in den Zellen. Die bringen ihren eigenen Rahmen mit und klebten damit sichtbar
   aneinander - zwischen zwei Feldern lagen 6px, weniger als die Höhe ihrer eigenen Rundung.
   Die Kopfzeile behält etwas mehr als die Zeilen darunter: Sie ist eine gefüllte Fläche und wirkt sonst gedrückt. */
.settingsTable th {
	padding: 0.45rem 0.5rem;
}

.settingsTable td {
	padding: 0.3rem 0.5rem;
}

/* Unter dem Tabellenkopf noch einmal mehr: Er ist eine zusammenhängende Fläche mit eigenem Hintergrund, und ein
   Feld unmittelbar darunter wirkte, als gehörte es hinein statt darunter. Die Luft auf beide Seiten verteilt,
   weil eine Tabellenzeile keinen Außenabstand kennt. */
.settingsTable thead th {
	padding-bottom: 0.55rem;
}

.settingsTable tbody tr:first-child td {
	padding-top: 0.75rem;
}

/* Nur Eingabefelder füllen ihre Spalte - in ein Auswahlfeld tippt niemand etwas Langes, und über die halbe
   Spaltenbreite gezogen sah die Rollenauswahl aus, als fehlte ihr etwas (gemessen 290px für "admin"). */
.settingsTable input {
	width: 100%;
}

/* Ohne Untergrenze bestimmt der Inhalt die Spaltenbreite, und ein leeres Feld (etwa ein noch nicht gesetzter
   FTP-Benutzer) fiele auf wenige Pixel zusammen. Nur Zellen mit Eingabefeld, damit die Spalte mit den
   Aktionssymbolen schmal bleiben darf. */
.settingsTable td:has(input),
.settingsTable td:has(select) {
	min-width: 8rem;
}

.settingsTable .settingsTableActions {
	text-align: right;
	white-space: nowrap;
}

/* Ports und HTTPS einer Dreambox: eine ausklappbare Zeile unter der eigentlichen, statt weiterer Spalten. Sie
   stehen fast immer auf den Vorgabewerten (80/8001/21, kein HTTPS) - als eigene Spalten würden sie die Tabelle
   dauerhaft verbreitern für etwas, das man einmal im Leben anfasst. */
.boxAdvancedRow {
	display: none;
}

.boxAdvancedRow.open {
	display: table-row;
}

/* Eine leichte Fläche darunter, damit die aufgeklappten Felder sichtbar zu der Zeile darüber gehören: Ohne sie
   stand der Hinweistext frei zwischen zwei Boxen und sah aus, als gälte er für die folgende. */
.boxAdvancedRow.open > td {
	background: rgba(102, 153, 221, 0.07);
	padding-bottom: 0.6rem;
}

/* Der negative Abstand von .settingsHint zieht den Text dicht unter ein Feld - hier steht er unter einer ganzen
   Zeile von Feldern und braucht Luft nach oben statt nach unten. */
.boxAdvancedRow .settingsHint {
	margin: 0.5rem 0 0 0;
}

.boxAdvanced {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 1.2rem;
}

/* Dieselbe Textfarbe wie die Beschriftungen der übrigen Formulare (siehe .settingsForm label). */
.boxAdvanced label {
	align-items: center;
	color: var(--text);
	display: flex;
	font-size: 0.85rem;
	gap: 0.4rem;
	white-space: nowrap;
}

/* Ohne das zögen die Felder über die ganze Zeilenbreite (siehe ".settingsTable input"), was in einer Zelle mit
   colspan die volle Tabelle ist. Eine Portnummer hat höchstens fünf Ziffern, ein Kontrollkästchen gar keine. */
.boxAdvanced input[type="number"] {
	width: 5.5rem;
}

.boxAdvanced .boxAdvancedCheck input {
	width: auto;
}

/* Ohne FTP gibt es auch keinen FTP-Port. Bewusst allein per CSS und ohne JavaScript: Das Feld bleibt im Markup und
   wird beim Speichern normal mitgelesen, so dass ein einmal eingetragener Port erhalten bleibt, wenn FTP
   zwischendurch aus und wieder an war. */
.boxAdvanced:has(.boxFtpEnabled:not(:checked)) .boxFtpPortField {
	display: none;
}

/* Die Warnung zu HTTPS nur, solange HTTPS auch angehakt ist. Das :has muss an der Zeile ansetzen und nicht an
   .boxAdvanced: Der Hinweis steht nicht in der Feldzeile, sondern darunter - gemeinsamer Vorfahre ist erst die
   Tabellenzeile. */
.boxAdvancedRow:has(.boxHttps:not(:checked)) .boxHttpsHint {
	display: none;
}

/* Ohne das ist die ausgegraute Attrappe (ein span) sichtbar größer als die echten Schaltflächen daneben: .iconBtn
   setzt keine Schriftgröße, und ein <button> erbt sie nicht, sondern bekommt die kleinere Vorgabe des Browsers.
   Beide auf die Schriftgröße der Tabelle zu setzen, gleicht sie an. */
.settingsTable .iconBtn {
	font-size: inherit;
}

/* Trennt Administratoren von den übrigen Rollen (siehe UserHandler#getUsers). Bewusst die zurückhaltendste Linie
   der Anwendung (--line-subtle, "die Andeutung einer Kante innerhalb einer Fläche"): Sie gliedert eine Liste
   *innerhalb* eines Bereichs und darf deshalb nicht so schwer wiegen wie die Linie unter dessen Überschrift, die
   2px in --line trägt (siehe .settingsPanelTitle).
   Die Luft darum herum macht die Gruppierung mehr aus als die Linie selbst. Sie muss auf zwei Zeilen verteilt
   werden - unter der letzten davor und über der ersten danach -, weil eine Tabellenzeile keinen Außenabstand
   kennt. Dafür das :has() auf die Vorgängerzeile; einen Vorgänger-Selektor gibt es sonst nicht. */
.settingsTable .settingsUserGroupStart td {
	border-top: 1px solid var(--line-subtle);
	padding-top: 0.7rem;
}

.settingsTable tr:has(+ .settingsUserGroupStart) td {
	padding-bottom: 0.7rem;
}

/* Erläuterung unter einem Feld - etwa welches ffmpeg die automatische Suche tatsächlich gefunden hat. Steht
   unmittelbar am Feld statt in einer Fußnote: Sie beantwortet die Frage, die man beim Ausfüllen hat. */
.settingsHint {
	color: var(--text-muted);
	font-size: 0.85rem;
	margin: -0.3rem 0 0.6rem 0;
	overflow-wrap: anywhere;
}

/* Der Pfad ist die Antwort, der Rest drumherum nur Beschriftung - deshalb bekommt er dasselbe Blau, das in der
   ganzen Anwendung einen Wert kennzeichnet (siehe .content .db-value). Die Versionszeile darunter bleibt gedämpft:
   Sie ist Zusatz, nicht die Antwort auf die Frage "welches ffmpeg denn nun". */
.settingsHint code {
	color: #6af;
	font-family: monospace, monospace;
	font-size: 0.95em;
}

.settingsHintWarn {
	color: #e55;
	margin-right: 0.35em;
}

/* "(gesetzt)" hinter der Beschriftung eines Geheimnisses, das nicht angezeigt wird - grün wie überall das
   Erledigte (siehe --accent-watched). */
.settingsIsSet {
	color: var(--accent-watched);
	font-size: 0.85em;
}

.settingsUserSelf {
	color: var(--text-muted);
	font-size: 0.85em;
	margin-left: 0.35em;
}

/* Name und das "(du)" dahinter gehören in eine Zeile: Umbrochen sah der Zusatz aus, als stünde dort ein zweiter
   Benutzer. Die Spalte wird dadurch so breit wie der längste Name - auf dem Handy heißt das etwas mehr
   waagerechtes Scrollen, was hier ohnehin schon nötig ist. Die Obergrenze dafür setzt das maxlength am Feld
   "Benutzer anlegen" (siehe settings.html). */
.settingsUserName {
	white-space: nowrap;
}

.settingsUserSeen {
	color: var(--text-muted);
	white-space: nowrap;
}

/* Der Punkt für "gerade aktiv" - grün wie überall in der Anwendung "gesehen"/erledigt (siehe --accent-watched). */
.settingsUserActive {
	background: var(--accent-watched);
	border-radius: 50%;
	display: inline-block;
	height: 0.5em;
	margin-right: 0.4em;
	vertical-align: middle;
	width: 0.5em;
}

/* Schmale Bildschirme: Menü und Bereich teilen sich den Platz nicht, sondern lösen einander ab - erst die Liste
   als ganze Seite, nach der Auswahl der Bereich mit Zurück-Knopf. Nebeneinander blieben von 390px Breite abzüglich
   des Menüs kaum 240px für das Formular übrig. */
@media (max-width: 640px) {
	.settingsLayout {
		display: block;
	}

	/* Als durchgehende Liste statt einzelner Pillen: Über die volle Breite gezogen sind es keine Schaltflächen
	   mehr, sondern Zeilen - dieselbe Form, die auch sonst auf dem Handy eine Auswahl trägt. */
	.settingsNav {
		gap: 0;
	}

	.settingsNavItem {
		border-bottom: 1px solid var(--line-subtle);
		border-radius: 0;
		padding: 0.9rem 0.4rem;
	}

	/* Das Chevron macht sichtbar, dass der Eintrag hier auf eine eigene Ansicht führt - anders als auf breiten
	   Bildschirmen, wo der Bereich einfach daneben stehen bleibt. */
	.settingsNavItem::after {
		color: var(--text-muted);
		content: "\203A";
		margin-left: auto;
	}

	/* Die Hervorhebung des gewählten Eintrags entfällt: Sobald ein Bereich offen ist, ist das Menü ohnehin nicht
	   mehr zu sehen, und beim Zurückgehen wäre eine hervorgehobene Zeile eine Aussage über nichts. */
	.settingsNavItem.active {
		background: none;
		color: var(--control-text);
	}

	/* Das Attribut setzt settings.js, sobald ein Bereich gewählt ist - auf breiten Bildschirmen ist es immer
	   gesetzt, deshalb steht diese Regel nur hier. */
	.settingsLayout[data-panel] .settingsNav {
		display: none;
	}

	/* Breiter als die 8rem auf großen Bildschirmen, nicht schmaler: Die Tabelle scrollt hier ohnehin waagerecht,
	   also kostet Breite nichts - abgeschnittener Text dagegen schon. Bei 8rem endete die Adresse als
	   "192.168.178.2" und der Platzhalter als "Passwort ges". */
	.settingsTable td:has(input),
	.settingsTable td:has(select) {
		min-width: 11rem;
	}

	/* Zurücknehmen, was "table td" weiter unten für schmale Bildschirme setzt: break-all trennt mitten im Wort,
	   und das zerlegte hier das "(du)" hinter dem eigenen Namen nach dem "d". Hier gefahrlos, weil in dieser
	   Tabelle nur kurze Wörter stehen - kein Dateiname, der für sich genommen breiter als die Spalte wäre
	   (dieselbe Überlegung wie bei .cacheTable). */
	.settingsTable td {
		overflow-wrap: break-word;
		word-break: normal;
	}

	.settingsBack {
		align-items: center;
		display: inline-flex;
	}
}

/* Anmeldeseite --------------------------------------------------------------------------------- */

/* Steht für sich allein, ohne Kopfzeile und Seitenleiste (siehe login.html). Der Kasten sitzt waagerecht mittig und
   senkrecht im oberen Drittel statt exakt mittig: Auf dem Handy klappt beim Tippen die Tastatur auf, und ein mittig
   zentriertes Formular rutscht dann unter sie. */
.loginBody {
	align-items: center;
	background: var(--page-bg);
	display: flex;
	justify-content: center;
	min-height: 100dvh;
	padding: 1rem;
}

/* display und margin-top überschreiben die Regel für "main" weiter oben: Die trägt sonst das Flex-Layout der
   Hauptseite (Seitenleiste neben Inhalt) hier herein und stellt das Logo neben das Formular statt darüber. */
.loginBox {
	align-self: start;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 10px;
	display: block;
	margin-top: max(2rem, 12dvh);
	max-width: 22rem;
	padding: 1.5rem;
	width: 100%;
}

/* position: relative als Anker für das TEST-Schild: Es ist absolut positioniert (siehe .testTag) und landete ohne
   positionierten Vorfahren in der Ecke des Fensters statt neben dem Logo. */
.loginLogo {
	align-items: center;
	display: flex;
	gap: 0.5rem;
	justify-content: center;
	margin-bottom: 1.5rem;
	position: relative;
}

.loginLogo img {
	height: 2.5rem;
}

.loginForm {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
}

.loginForm label {
	color: var(--text-muted);
	font-size: 0.85rem;
}

.loginForm input {
	margin-bottom: 0.75rem;
	width: 100%;
}

.loginSubmit {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--field-radius);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	gap: 0.4rem;
	height: var(--control-height);
	justify-content: center;
	margin-top: 0.25rem;
	width: 100%;
}

.loginSubmit:active {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

.loginError {
	align-items: center;
	color: #e55;
	display: flex;
	font-size: 0.9rem;
	gap: 0.4rem;
	margin-bottom: 0.5rem;
}

/* Ohne Seitenmenü fehlt dem Inhalt der linke Rand, den sonst die Leiste beisteuert (siehe .main-content) - die
   Kacheln klebten an der Fensterkante. */
body.portalMode .main-content {
	padding: 1.2rem;
}

/* Alle Portal-Regeln mit "body" davor: Ohne das verlieren sie gegen gleich spezifische Regeln, die weiter unten in
   dieser Datei stehen - der Gesehen-Schalter der Folgenkachel blieb genau so sichtbar
   (".tmdbEpisodeInfoTop .tmdbToggleWatchedBtn", Zeile ~9020). Ein Element davor genügt, um zu gewinnen, und ist
   weniger fehleranfällig, als diesen Block ans Dateiende zu verschieben und dort zu vergessen.

   Kacheln im Portal: reduziert auf das, was ein Streaming-Konto etwas angeht (siehe AccessControl).
   Bewusst über CSS und nicht über Bedingungen in den Makros: inc/tmdbMeta.html wird von vielen Seiten benutzt, eine
   Handvoll Regeln hier erwischt alle auf einmal, ohne gemeinsam genutzte Makros umzubauen. Der Preis ist, dass das
   Markup im Quelltext stehen bleibt - bei Sehstatus und Bewertungen ist das vertretbar, bei Geheimnissen wäre es das
   nicht. */
body.portalMode .tmdbBadge.watched,
body.portalMode .tmdbTileWatchedCount,
body.portalMode .tmdbTileMoreActions,
body.portalMode .tmdbTileActions,
body.portalMode .playFolderNextEpisode,
body.portalMode .playMovie {
	display: none;
}

/* Beide Balken raus - auch der für die Sammlung. Er beantwortet die Frage "wie vollständig ist mein Bestand", und
   die stellt sich nur, wer sammelt. Ob überhaupt etwas da ist, sagt weiterhin das Archiv-Zeichen an der Kachel
   (grau, wenn nur teilweise); genaue Zahlen stehen auf der Detailseite. */
body.portalMode .tmdbProgress,
body.portalMode .tmdbProgressTip {
	display: none;
}

/* Die Bezeichnung der Fassung vor den beiden Stream-Knöpfen - nur bei mehreren, sonst stünden dort mehrfach
   dieselben zwei Knöpfe ohne Unterscheidung (siehe tmdbmoviedetail.html). */
.portalStreamLabel {
	color: var(--text-muted);
	font-size: 0.85rem;
	margin-right: 0.2rem;
	white-space: nowrap;
}

/* Sämtliche "..."-Menüs. Fast jeder .actionWrapper der Anwendung umschließt genau ein solches Menü, deshalb die eine
   Regel statt einer Aufzählung einzelner Stellen. Was darin an Erlaubtem stand - die Stream-Knöpfe - steht im Portal
   jetzt frei daneben (siehe tmdbmoviedetail.html). */
body.portalMode .actionWrapper {
	display: none;
}

/* Die Ausnahmen - und sie waren ein echter Fehler. Nachgezählt sind es 34 .actionWrapper, nicht 13, und vier davon
   sind kein "..."-Menü, sondern tragen Auskünfte, die einen Zuschauer sehr wohl angehen. Sie verschwanden trotzdem.

   Bei dreien fällt es nur im aufwendigeren Fall auf, was das Suchen erschwert hat: Eine einzelne Tonspur, ein einzelner
   Trailer und eine einzelne Bewertungsquelle stehen als schlichtes Element da und blieben sichtbar - erst bei mehreren
   wird daraus ein Klappmenü, und genau der informativere Fall fiel weg.

   - Sortier-Pille (inc/tools.html#sort_flyout): Sortieren ändert nichts, wie Suche und Filter, die bewusst dableiben.
     Sichtbar wurde es daran, dass die Filterzeile zu weit eingerückt aussah - der leere .sortActions-Container blieb
     als Flex-Element stehen und steuerte weiter seinen Abstand bei.
   - Bewertung (#ratingFlyout): Auf den Kacheln steht sie, auf der Detailseite fehlte sie.
   - Technik-Pillen (#techPills): Tonspuren und Untertitel der Aufnahme - was man vor dem Abspielen wissen will.
   - Trailer und lokale Videoclips (#videoLinks/#localVideoLinks): gehören zum Anschauen, nicht zur Verwaltung.

   Die pauschale Regel darüber bleibt bewusst stehen: Ein neu hinzugefügtes Menü ist damit im Portal automatisch weg,
   statt vergessen zu werden - dieselbe Richtung wie bei AccessControl. Neue Ausnahmen kommen hierher. */
body.portalMode .sortActions .actionWrapper,
body.portalMode .tmdbTechActions .actionWrapper,
body.portalMode .actionWrapper:has(> .tmdbRating),
body.portalMode .actionWrapper:has(> .tmdbYoutubeLink),
body.portalMode .actionWrapper:has(> .tmdbLocalVideoLink) {
	display: block;
}

/* Der Sehstatus gehört dem Admin, nicht dem Streaming-Nutzer: Er sagt nichts darüber aus, was *der* schon gesehen
   hat, und einen eigenen führt DreamProxy für ihn nicht. Deshalb überall weg, nicht nur unveränderbar. */
body.portalMode .tmdbToggleWatchedBtn,
body.portalMode .tmdbStat.watched,
body.portalMode .tmdbAddRecordingBtn {
	display: none;
}

/* "Verknüpfte Inhalte": weder anlegen noch lösen. Das sind von Hand gepflegte Bezüge des Admins (Abschlussfilm zu
   einer Serie und dergleichen) - ein Streaming-Nutzer soll sie sehen, aber nicht anfassen. */
body.portalMode .tmdbRelatedAddBtn,
body.portalMode .tmdbRelatedRemoveBtn {
	display: none;
}

/* Die beiden Stream-Knöpfe stehen im Portal frei statt in einem "..."-Menü, wo sie ihr Aussehen herbekamen - ohne
   diese Regeln waren sie unformatierte Browser-Schaltflächen (heller Grund, schwarze Schrift, 2px Rand).
   Sie erben deshalb hier dasselbe Aussehen wie der Abspielen-Knopf, den sie ersetzen. */
.tmdbRecordingChip .streamMovie,
.tmdbRecordingChip .streamExternal {
	align-items: center;
	background: transparent;
	border: none;
	color: inherit;
	cursor: pointer;
	display: inline-flex;
	font-family: inherit;
	font-size: 0.82rem;
	gap: 0.35rem;
	/* Rechts genauso viel wie der Chip links vorgibt: Der Chip polstert links 0,8rem und rechts nur 0,3rem, weil
	   dort sonst das "..."-Menü sitzt - ohne das klebte die Beschriftung an der Kante. */
	padding: 0.3rem 0.5rem 0.3rem 0;
}

/* Kopfzeile des Portals: Zahnrad und Abmelden so groß wie die Box-Schaltflächen, an deren Stelle sie sitzen -
   als <a> statt <button> fielen sie sonst auf die Schriftgröße des Fließtextes zurück und wirkten verloren. */
body.portalMode .globalActions .iconBtn {
	font-size: 1.4rem;
	height: var(--control-height);
	width: var(--control-height);
}

/* Ohne Menü-Knopf links und mit nur zwei Symbolen rechts steht das Logo sonst angeklebt am linken Rand. Absolut
   zentriert und nicht per Flex-Verteilung: So sitzt es in der Mitte des Fensters, unabhängig davon, wie breit die
   Schaltflächen rechts gerade sind. */
body.portalMode header .logo {
	left: 50%;
	position: absolute;
	transform: translateX(-50%);
}

/* Der Filter nach Sehstatus: Er ändert zwar nichts, aber er filtert nach einer Angabe, die es im Portal sonst
   nirgends mehr gibt (siehe oben) - ein Filter auf Unsichtbares ist nur verwirrend. Der Sammlungs-Filter daneben
   bleibt, dessen Zeichen steht ja weiterhin an jeder Kachel. */
body.portalMode [data-flyout="Watched"] {
	display: none;
}

/* Der TMDB-Link war in der Kachel vor allem eine Abkürzung für den Admin; auf den Detailseiten steht er weiterhin.
   Der Trailer-Link (.tmdbYoutubeLink) bleibt - er gehört zum Anschauen. */
body.portalMode .tmdbTileLinks .tmdbExternalLink:not(.tmdbYoutubeLink) {
	display: none;
}

/* Bleibt von der Zeile nichts übrig, soll sie auch keinen Platz mehr beanspruchen. Übrig bleiben kann nur der
   Trailer-Link - alles andere darin ist oben ausgeblendet. */
body.portalMode .tmdbTileLinks:not(:has(.tmdbYoutubeLink)) {
	display: none;
}

/* Das Herz der Merkliste (siehe inc/tmdbMeta.html#watchlistHeart). Auf der Kachel sitzt es in derselben Zeile wie die
   Kennzeichen oben rechts und übernimmt deren Maße - so bleibt die Ecke ein Block statt zwei verschiedener Dinge
   nebeneinander. Ohne body.portalMode davor: Die Klasse gibt es sonst nirgends, und gerendert wird das Herz ohnehin
   nur im Portal. */
.tmdbWatchlistBtn {
	align-items: center;
	background: rgba(17,17,51,0.85);
	border: none;
	border-radius: 50%;
	color: #fff;
	cursor: pointer;
	display: flex;
	font-size: 1rem;
	height: 1.6rem;
	justify-content: center;
	padding: 0;
	width: 1.6rem;
}

.tmdbWatchlistBtn.on {
	color: var(--accent-watchlist);
}

/* Während die Antwort unterwegs ist: Der Knopf bleibt stehen, wird aber sichtbar taub - umgeschaltet wird erst, wenn
   der Server bestätigt hat (siehe watchlist.js). */
.tmdbWatchlistBtn:disabled {
	cursor: default;
	opacity: 0.5;
}

/* Auf den Detailseiten steht das Herz frei in der Kopfzeile statt klein auf einem Poster: ohne eigene Fläche und so
   hoch wie die Schaltflächen daneben. */
.tmdbWatchlistBtnLarge {
	background: none;
	font-size: 1.5rem;
	height: var(--control-height);
	width: var(--control-height);
}

/* Startseite eines Streaming-Kontos: Titel, zwei große Kacheln, darunter dieselben Posterreihen wie beim Admin.
   Senkrecht zentriert wird nichts mehr - die Seite ist jetzt voll genug, um von oben zu beginnen. */
.portalTitle {
	font-size: clamp(1.3rem, 3vw, 2.2rem);
	font-weight: bold;
	letter-spacing: 0.03em;
	margin: 0.5rem 0 1.2rem 0;
	text-align: center;
}

/* Immer zwei Spalten, auch auf dem Handy: Untereinander schöbe die zweite Kachel die Posterreihen aus dem Bild,
   und "Filme oder Serien" ist eine Entscheidung, die man nebeneinander trifft. */
.portalTiles {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(2, 1fr);
	margin: 0 auto 2rem auto;
	max-width: 44rem;
}

.portalTile {
	align-items: center;
	aspect-ratio: 16 / 9;
	background: linear-gradient(160deg, #22315c 0%, var(--surface) 60%);
	border: 1px solid var(--line);
	border-radius: 14px;
	color: var(--text);
	display: flex;
	justify-content: center;
	overflow: hidden;
	position: relative;
	text-decoration: none;
	transition: border-color 0.15s, transform 0.15s;
}

/* Kein :hover - die Anwendung verzichtet bewusst darauf (siehe [data-tooltip]); der Druckpunkt zeigt die Reaktion. */
.portalTile:active {
	border-color: var(--control-border-hover);
	transform: scale(0.99);
}

/* Das Postermosaik füllt die Kachel und liegt hinter dem Text. Stark abgedunkelt und leicht unscharf: Es soll nach
   Mediathek aussehen, nicht mit der Beschriftung um Aufmerksamkeit ringen. */
.portalTileMosaic {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	inset: 0;
	opacity: 0.35;
	position: absolute;
}

.portalTileMosaic img {
	filter: blur(1px);
	height: 100%;
	object-fit: cover;
	width: 100%;
}

/* Verlauf über dem Mosaik, damit die Beschriftung auf jedem Poster lesbar bleibt - ein Poster kann hell sein. */
.portalTile::after {
	background: linear-gradient(180deg, rgba(13, 20, 38, 0.35) 0%, rgba(13, 20, 38, 0.85) 100%);
	content: "";
	inset: 0;
	position: absolute;
}

.portalTileBody {
	align-items: center;
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	/* Über den Verlauf, der als ::after eine eigene Ebene aufspannt. */
	position: relative;
	z-index: 1;
}

.portalTileBody i {
	color: #6af;
	font-size: clamp(1.8rem, 4vw, 3rem);
}

.portalTileName {
	font-size: clamp(1rem, 2vw, 1.6rem);
	font-weight: bold;
	letter-spacing: 0.05em;
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}

.portalTileCount {
	color: #cfe0f5;
	font-size: clamp(0.75rem, 1.2vw, 1rem);
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}

/* Hinweiskasten auf der Startseite, solange Dreambox oder Aufnahmeort fehlen (siehe index.html). Auffällig genug,
   um nach der Ersteinrichtung nicht übersehen zu werden, aber kein Fehler - deshalb der ruhige Blauton der Familie
   statt Rot. */
.setupTodo {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 6px;
	margin-bottom: 1rem;
	max-width: 46rem;
	padding: 0.8rem 1rem;
}

.setupTodoTitle {
	align-items: center;
	color: #fff;
	display: flex;
	font-weight: bold;
	gap: 0.4rem;
	margin-bottom: 0.4rem;
}

.setupTodo ul {
	color: var(--text-muted);
	line-height: 1.5;
	margin: 0;
	padding-left: 1.2rem;
}

.setupTodo a {
	color: #6af;
}

/* Einleitender Text der Ersteinrichtung, über dem Formular (siehe setup.html). */
.setupIntro {
	color: var(--text-muted);
	font-size: 0.9rem;
	line-height: 1.45;
	margin: 0 0 1.2rem 0;
	text-align: left;
}

/* System-Seite --------------------------------------------------------------------------------- */

/* Die Cache-Übersicht ist eine Lesetabelle ohne Aktionen: Sie soll nur so breit werden wie ihr Inhalt, statt
   sich über die ganze Seite zu ziehen und die vier Spalten weit auseinanderzureißen. */
.cacheTable {
	max-width: 60rem;
	width: 100%;
}

.cacheTable .cacheContent,
.cacheTable .cacheInterval {
	color: var(--text-muted);
}

/* Auffällig, aber nicht alarmierend: Die Zeile bleibt lesbar, das Symbol trägt die Aussage. Ein "hängt" heißt
   nicht zwingend Fehler - nach einem Neustart ist der 24-Stunden-Cache schlicht noch nie gelaufen. */
.cacheTable .cacheStale td {
	color: #e55;
}

.cacheTable .cacheStaleIcon {
	margin-right: 0.35em;
}

@media (max-width: 640px) {
	/* Vier Spalten passen hier nicht nebeneinander: .defaultTable td trennt notfalls mitten im Wort
	   (overflow-wrap: anywhere), aus "Aufnahmeorte" wird dann "Aufnah meorte". Das Intervall weicht als erstes -
	   es ist unveränderlicher Zusatz, kein Zustand. Die verbleibenden Spalten brechen wieder nur zwischen Wörtern;
	   die Inhaltsspalte behält das harte Trennen, weil dort die längsten Texte stehen. */
	.cacheTable .cacheInterval,
	.cacheTable th:nth-child(4) {
		display: none;
	}

	/* word-break muss mit zurückgenommen werden, nicht nur overflow-wrap: Auf schmalen Bildschirmen setzt weiter
	   unten "table td" beides, und break-all trennt für sich genommen schon mitten im Wort. Hier ist das gefahrlos,
	   anders als bei den Aufnahme-Tabellen: In dieser Tabelle stehen nur kurze Wörter, kein Dateiname, der für
	   sich genommen breiter als die Spalte wäre. */
	.cacheTable td {
		overflow-wrap: normal;
		word-break: normal;
	}
}

/* Werkzeuge für die Entwicklung, kein Alltagsweg: klein, grau und am Seitenende - vorher waren es vier
   Kacheln in voller Größe, die mehr Gewicht hatten als alles darüber. */
.devLinks {
	display: flex;
	flex-wrap: wrap;
	gap: 1.25rem;
	margin-top: 2rem;
}

.devLinks a {
	align-items: center;
	color: var(--text-muted);
	display: inline-flex;
	font-size: 0.85rem;
	gap: 0.35em;
	text-decoration: none;
}

.devLinks a:active {
	color: #fff;
}

/* Screenshot ----------------------------------------------------------------------------------- */

.screenshotFormatSelect {
	background-color: var(--control-bg);
	border: 1px solid var(--line);
	border-radius: 3px;
	color: #ddd;
	font-size: 0.9em;
	padding: 3px 5px;
}

.screenshots {
	margin: 1rem 0 1rem 0;
}

.screenshotTiles {
	overflow: hidden;
}

.screenshotImage {
	display: block;
	max-width: 100%;
}

.screenshotTile {
	background: var(--surface);
	border: 1px solid var(--line-subtle);
	border-radius: 8px;
	color: #ddd;
	display: flex;
	flex-direction: column;
	float: left;
	gap: 0.4rem;
	margin: 0 1rem 1rem 0;
	padding: 1rem;
	text-align: center;
	width: 15rem;
}

.screenshotDateTime {
	font-size: 0.75rem;
	margin-top: 0.5rem;
}

.screenshotFormat {
	color: #999;
}

.currentScreenshot {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 6px;
	color: #ddd;
	/*float: right;*/
	margin-bottom: 1rem;
	max-width: 37rem;
	padding: 1rem;
}

.currentScreenshotImage {
	display: block;
	height: auto;
	max-width: 100%;
}

.deleteScreenshotBtn {
	cursor: pointer;
	font-size: 1.2em;
	margin-left: 0.25em;
	vertical-align: middle;
}

/* Tooltip -------------------------------------------------------------------------------------- */

[data-tooltip] {
	cursor: help;
	position: relative;
}

[data-tooltip]:before, [data-tooltip]:after {
	opacity: 0;
	pointer-events: none;
	visibility: hidden;
	z-index: 200;
}

[data-tooltip]:before {
	background-color: var(--surface-raised);
	border-radius: 6px;
	bottom: 100%;
	color: #fff;
	content: attr(data-tooltip);
	font-size: 0.9em;
	font-weight: normal;
	line-height: 1.5em;
	margin-bottom: 5px;
	/* Schmaler als das Fenster und umbrechend: Eine Blase, die breiter als der sichtbare Bereich ist, lässt sich
	   auch durch Verschieben nicht mehr hineinbekommen (siehe positionTooltip in chrome.js). Kurze Texte -
	   der Normalfall - bleiben durch width:fit-content weiterhin einzeilig. */
	max-width: min(24rem, calc(100vw - 1rem));
	padding: 0.25em 1em;
	position: absolute;
	right: 0;
	text-align: center;
	/* Waagerechte Korrektur aus chrome.js; ohne sie bleibt es bei der rechtsbündigen Ausrichtung: */
	transform: translateX(var(--tooltipShift, 0));
	width: fit-content;
}

[data-tooltip]:after {
	border-top: 5px solid hsla(0, 0%, 20%, 0.9);
	border-right: 5px solid transparent;
	border-left: 5px solid transparent;
	bottom: 100%;
	content: " ";
	font-size: 0;
	left: 50%;
	line-height: 0;
	margin-bottom: 0;
	margin-left: -5px;
	position: absolute;
	width: 0;
}

/* Nach unten geklappt, weil über dem Element zu wenig Platz ist (gesetzt von positionTooltip in chrome.js).
   Der Pfeil wird dabei mitgedreht: Sein oberer Rand trägt die Farbe, für die Spitze nach oben muss sie an den
   unteren. */
.tooltipBelow:before {
	bottom: auto;
	margin-bottom: 0;
	margin-top: 5px;
	top: 100%;
}

.tooltipBelow:after {
	border-bottom: 5px solid hsla(0, 0%, 20%, 0.9);
	border-top-color: transparent;
	bottom: auto;
	top: 100%;
}

/* Der einzige verbliebene Hover-Effekt, und das mit Absicht - hier ist das Kleben auf Touch-Geräten kein Fehler,
   sondern der einzige Weg, den Tooltip überhaupt zu lesen: Angetippt bleibt er stehen, bis daneben getippt wird.
   Deshalb weder :active (nur sichtbar, solange gedrückt wird) noch eine Eingrenzung per @media (hover: hover),
   die ihn auf Touch-Geräten ganz verschlucken würde. Wo das Stehenbleiben stört, trägt das Element stattdessen
   ein title-Attribut. */
[data-tooltip]:hover:before, [data-tooltip]:hover:after {
	opacity: 1;
	pointer-events: auto;
	visibility: visible;
}

.tippy-box {
	background-color: var(--surface-raised);
	padding: 0 3px 5px 3px;
	width: 50em;
	z-index: 200;
}
.tippy-content {
	font-family: monospace;
	font-size: 1em;
	overflow: hidden;
}

/* Toast Notification --------------------------------------------------------------------------- */

/* Läuft als "manual" Popover (siehe toast.js) statt als gewöhnliches position:fixed-Element, damit sie auch über
   einem offenen <dialog> sichtbar ist - ein <dialog> wird beim Öffnen in den Browser-"Top Layer" gehoben, der immer
   über gewöhnlich positionierten Elementen liegt, egal wie hoch deren z-index ist. Popover landen ebenfalls im Top
   Layer und darüber, wenn sie nach dem Dialog geöffnet werden. border/bottom/right setzen dabei die abweichenden
   UA-Vorgaben des [popover]-Attributs zurück (border: solid, inset: 0), die sonst durchschlagen würden. */
.toast {
	background-color: var(--surface-raised);
	border: none;
	border-radius: 10px;
	bottom: auto;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.7);
	color: var(--text);
	left: 50%;
	max-width: 40vw;
	min-width: 250px;
	opacity: 0;
	padding: 1em 1.5em;
	pointer-events: none;
	position: fixed;
	right: auto;
	text-align: center;
	top: 1em;
	transform: translateX(-50%);
	transition: opacity 0.3s ease-in-out;
	visibility: hidden;
	z-index: 1000;
}

.toast.show {
	opacity: 1;
	pointer-events: auto;
	visibility: visible;
}

.toast.info {
	background-color: var(--surface-raised);
	border: 1px solid var(--control-border);
	color: #fff;
}

.toast.success {
	background-color: #363;
	border: 1px solid #6b6;
	color: #fff;
}

.toast.error {
	background-color: #633;
	border: 1px solid #b66;
	color: #fff;
}

.default-dialog {
	background: var(--surface-dialog);
	border: 1px solid var(--control-border);
	border-radius: 12px;
	box-shadow: 0 8px 24px rgba(0,0,0,0.7);
	color: var(--text);
	max-width: min(40rem, 100%);
	padding: 0;
}

.default-dialog-large {
	flex: max-content;
	max-width: none;
}

/*
 * Dialog, der zusätzlich die volle Fensterhöhe nutzt (statt nur so hoch zu sein wie sein Inhalt) - für Dialoge mit
 * langen, scrollenden Listen wie die TMDB-Suche: sonst bliebe unten Platz ungenutzt, während die Trefferliste in
 * einem schmalen Ausschnitt scrollt. Der Rand von 1rem oben/unten hält den Dialog vom Fensterrand weg.
 *
 * Der Inhalt wird dafür zur Flex-Spalte, damit das scrollende Element darin (siehe .default-dialog-tall .tmdbSearchResults)
 * den verbleibenden Raum bekommt; min-height/overflow sorgen dafür, dass es selbst scrollt, statt den Dialog zu dehnen.
 */
.default-dialog-tall {
	display: flex;
	flex-direction: column;
	height: calc(100% - 2rem);
}

.default-dialog-tall .default-dialog-content {
	display: flex;
	flex-direction: column;
	min-height: 0;
	overflow: hidden;
}

/* Suchzeile und Schaltflächen behalten ihre Höhe, nur die Trefferliste wächst und scrollt: */
.default-dialog-tall .tmdbSearchRow,
.default-dialog-tall .tmdbEpisodeSearchRow,
.default-dialog-tall .tmdbScanReviewBar,
.default-dialog-tall .default-dialog-actions {
	flex: none;
}

/* Die Flyouts in der Suchzeile (Tags in der Folgensuche, Suchoptionen in der TMDB-Suche) klappen absolut positioniert
   über die Trefferliste - das overflow:hidden oben würde sie abschneiden. Sichtbar wurde das nur, solange die Liste
   noch leer war: Danach reicht der Inhalt tief genug, dass das Panel innerhalb des abgeschnittenen Bereichs bleibt.
   Gescrollt wird ohnehin nur die Trefferliste selbst (beide bringen overflow-y mit), der Dialoginhalt muss dafür
   nichts abschneiden. */
#tmdbEpisodeSearchDialog .default-dialog-content,
#tmdbSearchDialog .default-dialog-content {
	overflow: visible;
}

/* Der Tag-Button sitzt am rechten Rand der Suchzeile; nach links aufklappen hält das Panel innerhalb des Dialogs.
   Mit dem sonst üblichen left:0 ragte es darüber hinaus und schöbe den mittig ausgerichteten Dialog aus dem Bild. */
#tmdbEpisodeSearchTagFilter .filterFlyoutPanel {
	left: auto;
	right: 0;
}

.default-dialog-tall .tmdbSearchResults,
.default-dialog-tall .tmdbEpisodeSearchResults,
.default-dialog-tall .tmdbScanReviewList {
	flex: 1;
	max-height: none;
	min-height: 0;
}

/* Das Scan-Ergebnis nimmt die volle Höhe nur, wenn die Liste sie braucht - daher Obergrenze statt fester Höhe. Die
   Suche darf fest hoch bleiben: Dort tippt man weiter und lädt laufend neue Treffer nach, ein springender Dialog wäre
   dabei unruhig. Das Ergebnis dagegen steht einmal fest, und bei zwei Treffern bliebe der halbe Dialog leer. */
#tmdbScanReviewDialog .default-dialog-tall {
	height: auto;
	max-height: calc(100% - 2rem);
}

.default-dialog-backdrop[open] {
	display: flex;
	justify-content: center;
	align-items: center;
	height: 100vh;
	margin: 0;
	max-height: 100vh;
	max-width: 100vw;
	padding: 0;
	position: fixed;
	width: 100vw;
}

.default-dialog::backdrop,
.default-dialog-backdrop {
	backdrop-filter: blur(2px);
	background: rgba(0,0,0,0.6);
}

/* Groß-Ansicht eines einzelnen Bilds (z.B. Episoden-Still), siehe openImageLightbox() in dialogs.js. Kein
   .default-dialog-Wrapper nötig: die Backdrop-Klick-Logik oben schließt hier bei jedem Klick, auch auf das Bild
   selbst - genau das gewünschte Verhalten, weil es innerhalb des Bilds nichts zu bedienen gibt. */
.imageLightboxBackdrop {
	border: none;
	cursor: zoom-out;
	max-width: 100vw;
	max-height: 100vh;
}

/* Höhere Spezifität als .default-dialog-backdrop[open] (Klasse+Attribut) nötig, sonst gewinnt dessen padding:0. */
.imageLightboxBackdrop[open] {
	padding: 1.5rem;
}

.imageLightboxImg {
	border-radius: 8px;
	box-shadow: 0 8px 24px rgba(0,0,0,0.7);
	max-width: 100%;
	max-height: calc(100vh - 3rem);
	object-fit: contain;
}

/* Wiedergabe auf dem eigenen Gerät (siehe player.js). Anders als die Bild-Groß-Ansicht schließt hier NICHT jeder
   Klick: Im Video wird bedient (Pause, Fortschritt, Lautstärke), und ein Fingertipp daneben soll nicht mitten im
   Film alles beenden - deshalb der eigene Schließknopf in der Kopfzeile. */
.videoPlayerBackdrop {
	background: transparent;
	border: none;
	max-width: 100vw;
	max-height: 100vh;
	overflow: visible;
}

.videoPlayerBackdrop[open] {
	padding: 0;
}

.videoPlayerBox {
	background: var(--surface-dialog);
	border: 1px solid var(--control-border);
	border-radius: 12px;
	box-shadow: 0 8px 24px rgba(0,0,0,0.7);
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

.videoPlayerHeader {
	align-items: center;
	background: var(--control-bg-hover);
	border-bottom: 1px solid var(--control-border);
	display: flex;
	gap: 0.5rem;
	min-height: 2.5rem;
	padding: 0 0.4rem 0 0.8rem;
}

/* Lange Aufnahmenamen dürfen den Kopf nicht auseinanderziehen - der Schließknopf muss erreichbar bleiben. */
.videoPlayerTitle {
	color: var(--control-text-hover);
	flex: 1;
	font-size: 0.95rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.videoPlayerClose {
	flex: none;
}

/* Das Video bestimmt die Größe des Dialogs, bleibt aber im Bildschirm: Platz für Kopfzeile und Rand abziehen.
   aspect-ratio ist hier das Entscheidende: Ohne die Angabe behält das Element seine Standardhöhe von 150px bzw.
   wird von max-height aufgezogen, und das Bild schwimmt mit schwarzen Streifen darin. Da praktisch alle Aufnahmen
   16:9 sind, sitzt der Rahmen damit auf dem Bild. Der schwarze Grund fängt die wenigen Ausnahmen ab. */
.videoPlayerVideo {
	aspect-ratio: 16 / 9;
	background: #000;
	display: block;
	height: auto;
	max-width: calc(100vw - 2rem);
	max-height: calc(100vh - 6rem);
	width: min(80rem, calc(100vw - 2rem));
}

.videoPlayerStatus {
	color: var(--text-muted);
	font-size: 0.85rem;
	padding: 0.5rem 0.8rem;
	text-align: center;
}

/* Kopfzeile des Dialogs: abgesetzt vom Dialogkörper, aber aus derselben Palette - und unten von einer Linie
   begrenzt, damit sie auch ohne starken Farbunterschied als Band lesbar bleibt. */
.default-dialog-header {
	align-items: center;
	background: var(--control-bg-hover);
	border-bottom: 1px solid var(--control-border);
	border-radius: 11px 11px 0 0; /* 1px weniger als der Dialog, sonst blitzt dessen Rahmen an den Ecken durch */
	display: flex;
	font-size: 1rem;
	gap: 0.5rem;
	margin: 0 0 0.3rem 0;
	min-height: 2.5rem;
	padding: 0.5rem 1rem;
}

/* Buttons in der Kopfzeile (Kopieren, Schließen): rechtsbündig neben dem Titel, der dafür in einem eigenen
   <span> steckt - sonst würde ein per .text() gesetzter Titel den Button mit entfernen. Flex statt float,
   damit Titel und Button beide vertikal mittig in der Kopfzeile sitzen: als Inline-Inhalt saß der Titel
   sonst auf der Textbaseline und hatte oben und unten unterschiedlich viel Luft. */
.default-dialog-header .copyToClipboardBtn,
.default-dialog-header .dialogCloseBtn {
	line-height: 1.3rem;
	margin-left: auto;
}

/* Schließen-Kreuz bewusst größer als die Standard-Button-Schriftgröße (~13px), damit es als Bedienelement
   klar erkennbar ist: */
.default-dialog-header .dialogCloseBtn i {
	font-size: 1.5rem;
	line-height: 1.5rem;
}

.default-dialog-content {
	padding: 1rem 1rem;
}

.default-dialog-content .default-dialog-msg {
	font-size: 0.95rem;
	margin: 0;
	white-space: pre-wrap;
}

.default-dialog-content .default-dialog-msg-small {
	color: #ccc;
	font-size: 0.75rem;
	margin: 0.5rem 0 0 0;
	white-space: pre-wrap;
}

.default-dialog-row,
.default-dialog-checkboxes {
	margin: 1rem 0;
}

/* Tag-Dialog einer Aufnahme (siehe inc/tmdbRecordingTagsDialog.html): Aufnahme-Auswahl oben, Anlegen-Zeile unten.
   Das :not([hidden]) ist nötig, weil ein gesetztes display sonst das hidden-Attribut überstimmt - die Auswahl
   erscheint nur bei mehreren Aufnahmen. */
.recordingTagsPicker:not([hidden]),
.recordingTagsAddRow {
	align-items: center;
	display: flex;
	gap: 0.5rem;
}

.recordingTagsPicker {
	margin-top: 0.5rem;
}

.recordingTagsPicker select {
	flex: 1;
	min-width: 0;
}

.recordingTagsAddRow .dialogInput {
	flex: 1;
	min-width: 0;
}

.default-dialog-row .defaultInput {
	width: 100%;
}

/* Im Dialog stehen die Kästchen als Zeilen im Formular, nicht als Chips: Fläche und Rahmen entfallen deshalb,
   nur das Kästchen selbst bleibt (gleiche Überlegung wie im Filter-Menü, siehe .filterFlyoutPanel). */
.default-dialog-row .defaultCheckboxLabel,
.default-dialog-checkboxes .defaultCheckboxLabel {
	background: transparent;
	border-color: transparent;
	padding-left: 0;
	padding-right: 0;
}

.default-dialog-row .defaultCheckboxLabel:active,
.default-dialog-checkboxes .defaultCheckboxLabel:active {
	background: transparent;
	border-color: transparent;
	color: var(--control-text-hover);
}

.default-dialog-table-row {
	max-height: 70vh;
	overflow: auto;
}

#tagManageDialog {
	max-width: min(48rem, 100%);
}

/* Der Textbereich bringt von sich aus nur die Breite seiner cols-Vorgabe mit (~20 Zeichen) - für Fließtext zu
   schmal, während der Dialog daneben noch Platz hätte (siehe inc/tmdbNoteDialog.html): */
#tmdbNoteInput {
	max-width: 100%;
	width: 32rem;
}

.tagManageTable {
	border: none;
	width: 100%;
}

.tagManageTable th {
	background: transparent;
	border: none;
}

.tagManageTable td {
	border: none;
}

/* Der Tabellen-Header sitzt ganz oben im scrollbaren .default-dialog-table-row (overflow: auto), das nach oben
   öffnende Standard-Tooltip (siehe "[data-tooltip]:before/:after") würde dort abgeschnitten - deshalb hier nach
   unten öffnen lassen. */
.tagManageTable th[data-tooltip]:before {
	bottom: auto;
	margin-bottom: 0;
	margin-top: 5px;
	top: 100%;
}

.tagManageTable th[data-tooltip]:after {
	border-bottom: 5px solid hsla(0, 0%, 20%, 0.9);
	border-top: none;
	bottom: auto;
	margin-bottom: 0;
	top: 100%;
}

#tagManageDialog .default-dialog-table-row {
	margin: 0.5rem 0;
}

#tagManageDialog .default-dialog-table-row table {
	margin: 0.25rem auto;
}

.tagManageTable th.tagManageCountCol,
.tagManageTable td.tagManageCountCol {
	text-align: right;
}

.tagManageTable th.tagManageCountCol i {
	font-size: 1rem;
}

.tagManageTable td.tagManageNameCol {
	font-weight: bold;
	overflow: hidden;
	text-overflow: ellipsis;
}

.tagManageTable td.tagManageActionsCol {
	text-align: right;
	white-space: nowrap;
}

.tagManageTable td.tagManageActionsCol button {
	margin: 0 0 0 0.3em;
}

.default-dialog-table-row table {
	margin: 0.5rem auto;
	width: 100%;
}

.default-dialog-actions {
	display: flex;
	gap: 0.6rem;
	justify-content: flex-end;
	margin: 1.5rem 0 0 0;
}

.default-dialog-actions .defaultBtn {
	margin: 0;
	min-width: 6.5rem;
}

#infoPopup .default-dialog-actions {
	margin: 0;
}
#infoPopup .default-dialog-actions .infoPopupBtn {
	margin-top: 1.5rem;
}

@keyframes spin {
	0% { transform: rotate(0deg); }
	100% { transform: rotate(360deg); }
}

/* Der Spinner soll senkrecht mittig zum Text seiner Meldung stehen, egal ob die eine Zeile hat oder zwei. Dafür wird
   die Meldung selbst zur Flex-Zeile, sobald sie einen Spinner enthält - der Text bildet darin das erste (anonyme)
   Flex-Element. Als gefloateter Block hing der Spinner stattdessen am oberen Rand der Meldung und saß bei
   einzeiligem Text sichtbar zu tief. Der Kindselektor grenzt die Regel auf den Spinner der Meldung selbst ein. */
.default-dialog-msg:has(> .infoPopupSpinner) {
	align-items: center;
	display: flex;
	gap: 1em;
}

.infoPopupSpinner {
	animation: spin 1.5s linear infinite;
	border: 4px solid var(--control-bg);
	border-radius: 50%;
	border-top: 4px solid #6af;
	display: block;
	/* Nicht mitschrumpfen und rechtsbündig bleiben - beides übernahm vorher der float. */
	flex: none;
	height: 1.5em;
	margin-left: auto;
	width: 1.5em;
}

/* Eine Icon-Schaltfläche, deren Aktion gerade läuft: Statt eines eigenen Spinners dreht sich ihr Sinnbild selbst -
   beim Aktualisieren-Knopf der Aufnahmen-Liste ist das ohnehin der Kreispfeil. Wichtig für den Refresh beim Neuladen
   der Seite (siehe movieList.js), denn dort gibt es sonst kein Zeichen dafür, dass noch etwas läuft. */
.iconBtnBusy i {
	animation: spin 1s linear infinite;
	display: inline-block;
}

/* Kleiner Inline-Spinner fürs Icon einer Schaltfläche mit länger laufender Aktion (z.B. TMDB-Verknüpfen) - dieselbe
   Drehanimation wie der Dialog-Spinner oben, aber inline im Buttontext statt als eigener Block. */
.tmdbBtnSpinner {
	animation: spin 1s linear infinite;
	display: inline-block;
}

.servicesTable .actions button,
.bouquetsTable .actions button,
.dayFiltersTable .actions button {
	padding: 0.25em 0.5em;
}

#showTimerLogDialog .default-dialog-row {
	margin: 0;
}
#showTimerLogDialog table {
	margin: 0.5rem auto;
	width: 100%;
}
#showTimerLogDialog table .code {
	text-align: center;
}

.default-dialog .defaultAccordion {
	margin-top: 1em;
}

/* Die Bereiche trennt eine schmale Lücke, durch die der Dialoghintergrund scheint, statt einer Trennlinie:
   Zugeklappt stoßen die Namensbänder sonst mit ihrer eigenen hellen Kante an die Linie und es sieht aus wie zwei
   Linien untereinander. overflow lässt die rechteckigen Bänder der Rundung des Rahmens folgen - sonst schaut in
   jeder der vier Rundungen ihre eckige Ecke heraus. */
.defaultAccordion {
	border: 1px solid var(--line);
	border-radius: 6px;
	color: var(--text);
	display: flex;
	flex-direction: column;
	gap: 3px;
	overflow: hidden;
	width: 100%;
}

.defaultAccordionItem {
	min-width: 31rem;
}

.defaultAccordionItemName {
	background-color: var(--surface-band);
	color: var(--table-header-text);
	cursor: pointer;
	padding: 0.3em 0.5em;
}
.defaultAccordionItemName i {
	float: right;
	line-height: 1.2em;
}
.defaultAccordionItem.open .openIcon,
.defaultAccordionItem .closeIcon {
	display: none;
}
.defaultAccordionItem .openIcon,
.defaultAccordionItem.open .closeIcon {
	display: block;
}

.defaultAccordionContent {
	padding: 0.75em 0.75em;
}

.textFiltersTable {
	width: 100%;
}
.textFiltersTable th {
	background: var(--table-header-bg);
	color: var(--table-header-text);
	font-weight: bold;
	padding: 0 7px;
}
.textFiltersTable td {
	padding: 0;
}
.textFiltersTable td.actions {
	padding: 0 7px;
}
.textFiltersTable .textFilter input {
	min-width: 20rem;
	width: 100%;
}

/* Modern select + button row --------------------------------------------------------------- */

.select-row {
	align-items: center;
	display: inline-flex;
	gap: 0.5rem;
	margin: 0.5rem 0 1rem 0;
}

.defaultSelect {
	/*appearance: none;*/
	background-color: var(--control-bg);
	/*background-image: linear-gradient(45deg, transparent 50%, #eee 50%), linear-gradient(135deg, #eee 50%, transparent 50%);
	background-position: calc(100% - 1rem) calc(50%), calc(100% - 1rem + 6px) calc(50%);
	background-size: 6px 6px, 6px 6px;
	background-repeat: no-repeat;*/
	border: 1px solid var(--control-border);
	border-radius: var(--field-radius);
	color: var(--control-text);
	font-family: Verdana, sans-serif;
	font-size: 0.9rem;
	height: var(--control-height);
	line-height: 1.4;
	max-width: 100%;
	padding: 0 2rem 0 0.75rem;
	position: relative;
}

.defaultSelect optgroup {
	color: #fff;
	font-style: normal;
	font-weight: bold;
}
.defaultSelect optgroup,
.defaultSelect option {
	background-color: var(--surface-raised);
	color: var(--control-text);
}
.defaultSelect option[data-is-info] {
	font-style: italic;
}
.defaultSelect option[disabled] {
	color: #999;
	font-style: italic;
}
.defaultSelect option[data-is-marker] {
	color: #d44;
	font-style: italic;
}

.defaultSelect:focus {
	border-color: var(--control-border-hover);
	box-shadow: 0 0 0 3px rgba(136,140,204,0.12);
	outline: none;
}

.modern-btn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	cursor: pointer;
	font-weight: bold;
	padding: 0.45rem 0.6rem;
}

.modern-btn:active {
	filter: brightness(0.95);
}

.modern-btn:active {
	transform: translateY(1px);
}

.modern-btn i {
	font-size: 1.1rem;
	line-height: 1;
}

/* ---------------------------------------------------------------------------------------------- */

/* Segmented toggle styles for index view */
/* Umschalter mehrerer Ansichten: außen eine Pille, innen die Segmente durch Trennlinien geteilt. Das gewählte
   Segment ist ausgefüllt - dieselben Farben, die ein Bedienelement beim Drücken trägt. */
.segmentedToggle {
	align-items: center;
	background: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	display: inline-flex;
	font-size: 0.85rem;
	height: var(--control-height);
	overflow: hidden; /* damit die ausgefüllten Endsegmente der Pillenform folgen */
	white-space: nowrap;
}

.segmentedToggle .seg-btn {
	align-items: center;
	border-right: 1px solid var(--control-border);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	gap: 0.3rem;
	height: 100%;
	padding: 0 0.8rem;
	text-decoration: none;
}

.segmentedToggle .seg-btn:last-child {
	border-right: none;
}

.segmentedToggle .seg-btn:active:not(.active) {
	background: var(--control-bg-hover);
	color: var(--control-text-hover);
}

.segmentedToggle .seg-btn.active {
	background: var(--control-bg-hover);
	color: var(--control-text-hover);
}

.segmentedToggle .seg-btn:focus-visible {
	outline: 2px solid var(--control-border-hover);
	outline-offset: -2px;
}

.segmentedToggle .prevNextButtons {
	align-items: center;
	display: inline-flex;
	height: 100%;
}

/* Der Abstand sitzt symmetrisch an jedem der beiden Pfeile selbst statt am Container außenrum - sonst
   steht das Icon nicht mittig in seiner Fläche (der Container-Rand zählt nur einseitig mit). */
.segmentedToggle .prevNextButtons > * {
	align-items: center;
	display: inline-flex;
	height: 100%;
	padding: 0 0.5rem;
}

/* Die beiden Pfeile setzen sich optisch voneinander ab wie die übrigen Segmente der Pille - derselbe
   Trennstrich wie bei .seg-btn, hier auf das erste der beiden Elemente (Link oder deaktivierter Pfeil). */
.segmentedToggle .prevNextButtons > :first-child {
	border-right: 1px solid var(--control-border);
}

/* Dashboard tiles (index overview) ------------------------------------------------------------- */

.content .dashboard {
	align-items: flex-start;
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 1rem;
	margin: 1rem 0 1rem 0;
}

/* Auf der System-Seite stehen die Kästen nebeneinander und sollen gleich hoch sein, statt jeder für sich an seinem
   Inhalt zu enden - sie tragen unterschiedlich viele Zeilen. flex-start oben verhindert genau das, deshalb hier
   stretch. Greift nur im Nebeneinander: Unterhalb von 1024px stapelt .dashboard zu einer Spalte (siehe dortige
   Media Query, die align-items ohnehin überschreibt), und in Spaltenrichtung bestimmt align-items die Breite. */
.content .dashboard-info {
	align-items: stretch;
}

.content .db-info {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 6px;
	color: #ddd;
	flex-grow: 1;
	max-width: 100%;
	padding: 0.8rem;
	width: 26rem;
}

/* Die vier Kästen der System-Seite brechen je nach Fensterbreite auf zwei Zeilen um. Ohne Obergrenze zöge sich ein
   allein stehender Kasten der letzten Zeile über die ganze Seite (flex-grow oben) - bei der User-Box mit ihren zwei
   Zeilen sieht das aus wie ein Fehler.
   Die Regel steht bewusst hier und nicht bei den übrigen System-Regeln weiter oben: Sie muss nach .content .db-info
   stehen, um dessen max-width zu schlagen (gleiche Spezifität, es gewinnt die spätere), und vor der
   1024px-Media-Query, die sie unterhalb wieder aufhebt - dort bekommt jeder Kasten die volle Breite. */
.dashboard-info .db-info {
	max-width: 34rem;
}

.content .db-info .db-headline {
	border-bottom: 2px solid var(--line);
	color: #fff;
	font-size: 1.1rem;
	font-weight: bold;
	letter-spacing: 0.2em;
	margin: 0 0 0.6rem 0;
	padding-bottom: 0.4rem;
	text-transform: uppercase;
}

.content .db-info .db-headline .iconBtn,
.content .db-info .db-headline .videoSizeIcon {
	font-size: 1rem;
	vertical-align: bottom;
}

.content .db-rows + .db-headline {
	margin-top: 1.5rem;
}

.content .db-info .db-headline-right {
	float: right;
	letter-spacing: normal;
	text-transform: none;
}

.content .db-info .db-headline-sub {
	color: #ccc;
	font-size: 0.9rem;
	font-weight: normal;
	letter-spacing: normal;
	text-transform: none;
}

.content .db-info .db-headline .db-headline-sub {
	line-height: 1.5rem;
}

.content .disabled,
.content .disabled i {
	color: #999;
}

.content .db-rows {
	display: grid;
	gap: 0.5rem;
}

.content .db-row {
	align-items: center;
	display: flex;
	font-size: 0.9rem;
	gap: 0.5rem;
	justify-content: space-between;
}

.content .db-value {
	color: #6af;
	font-weight: bold;
}

.content .db-sep {
	border: none;
	border-top: 1px solid var(--line);
	margin: 0.5em 0;
}

.content .tiles--flex {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
}

.content .tiles--grid {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(auto-fill, minmax(max(15vw, 9rem), 1fr));
}

.content .tile {
	background: var(--surface);
	border: 1px solid var(--line-subtle);
	border-radius: 8px;
	color: #ddd;
	padding: 1rem;
	text-align: center;
}

.content .tiles--flex .tile {
	flex-grow: 1;
	min-width: 9rem;
}

.content .tile .tileIcon {
	color: #68c;
	font-size: min(6rem, 10vw);
}

.content .tile .tileMetaIcon {
	font-weight: bold;
	margin-right: 0.2rem;
	margin-top: 0.5rem;
}

/* Angehobene Fläche statt des alten #335: das lag wie der frühere Seitenhintergrund bei 240° und fiel neben der
   entsättigten Kachel (223°) als Farbwechsel statt als Aufhellen ins Auge. */
.content .tile:active {
	background: var(--surface-raised);
	box-shadow: 0 6px 18px rgba(0,0,0,0.45);
	color: #fff;
}
.content .tile:active .tileIcon {
	color: #6af;
}
	
.content .tile .tile-text {
	font-size: 1rem;
	font-weight: bold;
	margin-top: 0.5rem;
}

.content .tile .tile-meta {
	color: #aaa;
	font-size: 0.85rem;
	margin-top: 0.3rem;
}

/* Startseite: Kacheln zu Gruppen zusammengefasst, analog zu den Trennlinien-Gruppen im Flyout-Menü,
   nur mit einem farbigen, senkrecht beschrifteten Balken statt einer einfachen Linie, weil hier
   mehrspaltig statt einspaltig gelayoutet wird. */
/* align-items: stretch (Default), damit nebeneinander stehende Gruppen gleich hoch werden - die
   Gruppen mit weniger Zeilen wachsen dabei auf die Höhe der größten, siehe .tile-row unten.
   Der Außenabstand saß früher am .dashboard-Wrapper, den die Startseite seit dem Wegfall der Info-Box
   nicht mehr braucht - die Gruppenkacheln stehen dort jetzt allein und über die volle Breite. */
.content .tiles--grouped {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	margin: 1rem 0;
}

.content .tile-group {
	background: var(--surface);
	border: 1px solid var(--line-subtle);
	border-radius: 8px;
	display: flex;
	flex-grow: 1;
	min-width: 16rem;
	overflow: hidden;
}

.content .tile-group-label {
	align-items: center;
	color: #fff;
	display: flex;
	flex-shrink: 0;
	font-size: 0.85rem;
	font-weight: bold;
	justify-content: center;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	width: 1.8rem;
}

.content .tile-group-label span {
	transform: rotate(180deg);
	writing-mode: vertical-rl;
}

.content .tile-group--recording .tile-group-label { background: var(--group-recording); }
.content .tile-group--mediathek .tile-group-label { background: var(--group-mediathek); }
.content .tile-group--misc .tile-group-label { background: var(--group-misc); }

.content .tile-group-rows {
	display: flex;
	flex-direction: column;
	flex-grow: 1;
}

/* flex: 1 verteilt die Höhe der Gruppenkachel gleichmäßig auf ihre Zeilen - Gruppen mit weniger
   Einträgen bekommen dadurch höhere Zeilen statt einer kürzeren Kachel. */
.content .tile-row {
	align-items: center;
	color: #ddd;
	display: flex;
	flex: 1;
	gap: 0.75rem;
	padding: 0.7rem 1rem;
	text-decoration: none;
}

.content .tile-row + .tile-row {
	border-top: 1px solid var(--line);
}

.content .tile-row:active {
	background: var(--surface-raised);
	color: #fff;
}

.content .tile-row .tileIcon {
	color: #68c;
	flex-shrink: 0;
	font-size: 1.8rem;
}

.content .tile-row:active .tileIcon {
	color: #6af;
}

.content .tile-row .tile-text {
	font-size: 1rem;
	font-weight: bold;
}

.content .tile-row .tile-meta {
	color: #aaa;
	font-size: 0.85rem;
	margin-top: 0.2rem;
}

.content .tile-row .tileMetaIcon {
	font-weight: bold;
	margin-right: 0.2rem;
}

/* Listen --------------------------------------------------------------------------------------- */

.listsPage .listsEditBar {
	display: none;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0 0 1rem 0;
}

.listsPage.editing .listsEditBar {
	display: flex;
}

.listsPage .listsEditBar .defaultBtn {
	margin: 0;
}

/* Der Bearbeiten-Umschalter ist ein <button> im .segmentedToggle (die übrigen sind Links): */
.segmentedToggle button.seg-btn {
	background: transparent;
	border: none;
	cursor: pointer;
	font-family: inherit;
	font-size: inherit;
}

.listsPage .listsEmpty,
.listsPage .listsNoSelection {
	color: #aaa;
	font-size: 0.9rem;
	margin: 0 0 0.5rem 0;
}

/* Aufteilung: links das Menü mit den Gruppen und Listen, rechts die ausgewählte Liste ----------- */

.listsPage .listsLayout {
	align-items: flex-start;
	display: flex;
	flex-direction: row;
	gap: 1rem;
}

.listsPage .listsContent {
	flex: 1;
	min-width: 0; /* damit das Kachelraster schmaler werden darf als sein Inhalt */
}

.listsPage .listsMenu {
	background-color: var(--surface);
	border: 1px solid var(--line);
	border-radius: 5px;
	flex-shrink: 0;
	max-height: calc(100dvh - 6em);
	overflow-y: auto;
	position: sticky;
	top: 5em;
	width: 15rem;
}

/* Die Menü-Einträge übernehmen die Optik von .flyout-item (siehe "Flyout Menu"), nur kompakter: */
.listsPage .listsMenu .flyout-item {
	padding: 0.6em 0.75em;
}

.listsPage .listsMenuGroupHeader {
	font-weight: bold;
}

.listsPage .listsMenuGroupHeader::after {
	content: "▼";
	font-size: 0.7em;
	margin-left: auto;
}

.listsPage .listsMenuGroup.open .listsMenuGroupHeader::after {
	content: "▲";
}

.listsPage .listsMenuGroup + .listsMenuGroup .listsMenuGroupHeader {
	border-top: 1px solid var(--line);
}

.listsPage .listsMenuSubmenu {
	display: none;
}

.listsPage .listsMenuGroup.open .listsMenuSubmenu {
	display: block;
}

.listsPage .listsMenu .flyout-submenu .flyout-item {
	padding: 0.45em 0.75em 0.45em 1.5em;
}

.listsPage .listsMenuName {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.listsPage .listsMenuCount {
	color: #999;
	font-size: 0.85em;
	font-weight: normal;
	margin-left: auto;
	padding-left: 0.5em;
}

.listsPage .listsMenuNoLists {
	color: #999;
	display: block;
	font-size: 0.85em;
	font-style: italic;
	padding: 0.45em 0.75em 0.6em 1.5em;
}

.listsPage .listGroupActions {
	display: none;
}

.listsPage.editing .listGroupActions {
	display: flex;
	justify-content: flex-end;
	padding: 0 0.5em 0.4em 0.5em;
}

/* Kopfzeile der angezeigten Liste --------------------------------------------------------------- */

.listsPage .mediaListHeader {
	align-items: center;
	border-bottom: 1px solid rgba(102, 153, 221, 0.35);
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0 0 0.75rem 0;
	padding: 0 0 0.25rem 0;
}

.listsPage .mediaListIcon {
	color: #68c;
	font-size: 1.4rem;
}

.listsPage .mediaListName {
	font-size: 1.1rem;
	font-weight: bold;
}

.listsPage .mediaListMeta {
	color: #aaa;
	font-size: 0.8rem;
	font-weight: normal;
}

.listsPage .mediaListEmpty {
	color: #aaa;
	font-size: 0.9rem;
	margin: 0 0 0.5rem 0;
}

/* Der erklärende Zusatz ist nur im Bearbeiten-Modus sichtbar: */
.listsPage .mediaListEmptyHint {
	display: none;
}

.listsPage.editing .mediaListEmptyHint {
	display: inline;
}

.listsPage .listItemMissing {
	color: #d44;
}

/* Einträge (Tiles) ----------------------------------------------------------------------------- */

.content .listsPage .tiles--grid {
	gap: 0.6rem;
	grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}

/* Die Kachel ist eine Flex-Spalte, damit Meta-Zeile und Aktions-Buttons am unteren Rand sitzen und dadurch in einer
   Reihe immer auf gleicher Höhe stehen, auch wenn manche Titel mehrzeilig sind: */
.content .listsPage .tile.listItem {
	display: flex;
	flex-direction: column;
	padding: 0.6rem 0.4rem 0.4rem 0.4rem;
}

.content .listsPage .tile.listItem .tileIcon {
	font-size: 2.4rem;
}

/* Der Titel bekommt den Platz zwischen Icon und Meta-Zeile und wird darin vertikal zentriert: */
.content .listsPage .tile.listItem .tile-text {
	align-items: center;
	display: flex;
	flex: 1;
	font-size: 0.9rem;
	justify-content: center;
	margin-top: 0.2rem;
	overflow-wrap: anywhere;
}

/* Die Meta-Zeile sitzt am unteren Ende der Kachel (der Link darüber ist "flex: 1" und füllt den restlichen Platz); Text und
   Play-Button (falls vorhanden) stehen als Gruppe zentriert nebeneinander: */
.content .listsPage .tile.listItem .tile-meta {
	align-items: center;
	display: flex;
	justify-content: center;
	margin-top: auto;
	padding-top: 0.2rem;
}

/* Als Flex-Item greift "margin-top" von .tileMetaIcon (siehe oben) hier tatsächlich, anders als vorher im Fließtext -
   "margin-right" ergibt weiterhin den Abstand zum Text daneben, wie vorher: */
.content .listsPage .tile.listItem .tile-meta .tileMetaIcon {
	margin-top: 0;
}

.content .listsPage .tile.listItem .tile-meta .listItemPlay {
	margin-left: 0.75rem;
}

.listsPage .listItemPlayLabel {
	margin-left: 0.3rem;
}

/* Der Link füllt die Kachel bis auf Meta-Zeile und Aktions-Buttons und ist selbst eine Flex-Spalte: */
.listsPage .listItemLink {
	color: inherit;
	display: flex;
	flex: 1;
	flex-direction: column;
	text-decoration: none;
}

.listsPage .listItem.missing .tileIcon,
.listsPage .listItem.missing .tile-meta {
	color: #d44;
}

.listsPage .listItemPlay {
	align-items: center;
	background-color: transparent;
	border: none;
	color: #fff;
	cursor: pointer;
	display: inline-flex;
	padding: 0;
}

.listsPage .listItemPlay i {
	font-size: 1.1rem;
}

/* Bearbeiten-Modus: die Aktions-Buttons sind nur darin sichtbar ---------------------------------- */

.listsPage .mediaListActions,
.listsPage .listItemActions {
	display: none;
}

.listsPage.editing .mediaListActions {
	display: inline-block;
}

.listsPage.editing .listItemActions {
	display: flex;
	justify-content: center;
	margin: 0.2rem 0 0 0;
}

/* Schmaler Bildschirm: das Menü wandert über den Inhalt ----------------------------------------- */

@media (max-width: 640px) {
	/* "align-items: stretch" ist hier wichtig: in der Spalte würde das flex-start von oben sonst dafür sorgen,
	   dass .listsContent auf seine Inhaltsbreite schrumpft statt die volle Breite zu nutzen. */
	.listsPage .listsLayout {
		align-items: stretch;
		flex-direction: column;
	}

	.listsPage .listsMenu {
		max-height: none;
		position: static;
		width: 100%;
	}

	/* Auf dem Handy passt bei 15rem nur noch eine Kachel pro Reihe, daher hier schmalere Kacheln: */
	.content .listsPage .tiles--grid {
		grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
	}
}

/* Dialoge (Listen) ----------------------------------------------------------------------------- */

.dialogField {
	align-items: center;
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.dialogLabel {
	display: inline-block;
	font-weight: bold;
	min-width: 5rem;
}

.dialogField .dialogInput {
	flex: 1;
	min-width: 12rem;
}

.default-dialog-row .defaultTextarea {
	font-family: monospace;
	font-size: 0.8rem;
	height: auto;
	line-height: 1.3;
	width: 100%;
}

/* Icon-Auswahl in den Bearbeiten-Dialogen von Listen und Kategorien (siehe inc/iconPicker.html); die Optik der
   Labels kommt von .hiddenRadio + label. */
.iconPicker {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	max-width: 22rem;
}

/* Feste Kantenlänge, damit die unterschiedlich breiten Icons trotzdem ein gleichmäßiges Raster ergeben: */
.iconPicker label {
	align-items: center;
	display: flex;
	font-size: 1.3rem;
	height: 2rem;
	justify-content: center;
	line-height: 1;
	padding: 0;
	width: 2rem;
}

/* Die Beschriftung fluchtet mit der ersten Icon-Reihe statt neben dem Block zentriert zu stehen: */
.dialogField:has(.iconPicker) {
	align-items: flex-start;
}

.selectListsGroup {
	color: #aaa;
	font-size: 0.8rem;
	margin: 0.5rem 0 0.2rem 0;
}

.selectListsCount {
	color: #999;
	font-size: 0.85em;
	margin-left: 0.4em;
}

/* Kategorien ----------------------------------------------------------------------------------- */

.categoriesPage .categoryGroupHeading {
	align-items: center;
	display: flex;
	font-size: 1.1rem;
	gap: 0.4rem;
	margin: 1.2rem 0 0.6rem 0;
}

.categoriesPage .categoriesEmpty {
	color: #aaa;
	font-size: 0.9rem;
	margin: 0 0 0.5rem 0;
}

/* Export/Import nur im Bearbeiten-Modus, wie die Leiste bei den Listen: */
.categoriesPage .categoryDetailIcon {
	color: #68c;
	margin-right: 0.3rem;
}

/* min(11rem, 47%) statt 11rem: auf dem Handy ist die Spalte schmaler als 2 x 11rem, es passte dort nur eine
   Kachel pro Zeile - breitgezogen und mit viel Leerraum. Der Prozentanteil deckelt die Mindestbreite genau dann,
   wenn 11rem nicht mehr zweimal hineinpassen, und lässt so immer zwei Kacheln nebeneinander zu. Auf größeren
   Bildschirmen ist 47% der Spalte weit mehr als 11rem, dort gewinnt weiterhin der feste Wert - die Darstellung
   bleibt also unverändert. */
.content .categoriesPage .tiles--grid {
	gap: 0.6rem;
	grid-template-columns: repeat(auto-fill, minmax(min(11rem, 47%), 1fr));
}

/* Die Kachel ist eine Flex-Spalte, damit Meta-Zeile und Aktions-Buttons am unteren Rand sitzen und dadurch in einer
   Reihe immer auf gleicher Höhe stehen, auch wenn manche Titel mehrzeilig sind (wie bei den Listen): */
.content .categoriesPage .tile.categoryTile,
.content .categoriesPage .tile.createCategoryBtn {
	display: flex;
	flex-direction: column;
	padding: 0.6rem 0.4rem 0.4rem 0.4rem;
}

.content .categoriesPage .tile .tileIcon {
	font-size: 2.4rem;
}

.content .categoriesPage .tile .tile-text {
	font-size: 0.9rem;
	margin-top: 0.3rem;
	overflow-wrap: anywhere;
}

.content .categoriesPage .tile .tile-meta {
	margin-top: auto;
	padding-top: 0.2rem;
}

.categoriesPage .categoryTileLink {
	color: inherit;
	display: flex;
	flex: 1;
	flex-direction: column;
	text-decoration: none;
}

/* Die "Neue Kategorie"-Kachel als Button, sonst mit derselben Optik wie die übrigen Kacheln: */
.content .categoriesPage .tile.createCategoryBtn {
	color: #aaa;
	cursor: pointer;
	font-family: inherit;
	justify-content: center;
}

/* Einträge einer Kategorie: die Kacheln sind dieselben wie in der Film-/Serienübersicht (siehe inc/tmdbMeta.html),
   ihre Optik kommt daher aus dem TMDB-Abschnitt. Hier nur der Eintrag, dessen TMDB-Entität es nicht mehr gibt: */
.categoriesPage .tmdbTile.missing .tmdbPosterPlaceholder,
.categoriesPage .tmdbTile.missing .tmdbTileTitle {
	color: #d44;
}

/* Bearbeiten-Modus: die Aktions-Buttons und die "Neue Kategorie"-Kachel sind nur darin sichtbar --- */

.categoriesPage .categoryActions,
.categoriesPage .categoryItemActions,
.categoriesPage .createCategoryBtn {
	display: none;
}

.categoriesPage.editing .categoryActions,
.categoriesPage.editing .categoryItemActions {
	display: flex;
	justify-content: center;
	margin: 0.2rem 0 0 0;
}

/* Die "Neue Kategorie"-Kachel braucht denselben Selektor-Zuschnitt wie die Regel, die ihr weiter oben zusammen mit
   den übrigen Kacheln display:flex gibt (.content .categoriesPage .tile.createCategoryBtn) - mit weniger Klassen
   verliert das Verstecken gegen sie, und die Kachel stand dauerhaft da statt nur im Bearbeiten-Modus: */
.content .categoriesPage .tile.createCategoryBtn {
	display: none;
}

.content .categoriesPage.editing .tile.createCategoryBtn {
	display: flex;
}

/* In einer Kategorie tritt die Aktionszeile des Eintrags an die Stelle der Zeile mit dem "..."-Menü. Wo diese sitzt,
   ist je nach Kachel verschieden: bei Film und Filmreihe neben den TMDB-/Trailer-Links, bei einer Serie neben
   "Nächste Folge" (deren Link-Zeile hat kein Menü und bleibt deshalb stehen). */
.categoriesPage.editing .tmdbTile .tmdbTileLinks:has(.tmdbTileMoreActions),
.categoriesPage.editing .tmdbTile .tmdbTileActions {
	display: none;
}

/* Remote Control ------------------------------------------------------------------------------- */

.remoteTextForm {
	margin-top: 1rem;
}

.remoteTextForm #remoteTextInput {
	max-width: 60vw;
	width: 30rem;
}

.remoteTextForm #remoteTextBtn {
	margin-right: 0;
	min-width: auto;
	padding: 0 0.5em 0 0.5em;
}

.remoteOptions {
	margin: 0.5rem 0;
}

.remote {
	background: #111111;
	border-radius: 28px;
	box-shadow: 0 0 0 2px #1a1a1a, 0 0 0 4px #3a3a3a, 0 20px 60px rgba(0, 0, 0, 0.8), inset 0 1px 0 rgba(255, 255, 255, 0.05);
	margin-top: 1rem;
	padding: 0.5em 1em;
	width: 240px;
}

.remote .section {
	padding: 0.6em 0;
}

.remote button {
	border: none;
	cursor: pointer;
	font-family: inherit;
	font-weight: 700;
	font-size: 0.75rem;
	height: 2.5rem;
	letter-spacing: 0.05em;
	transition: filter 0.08s, transform 0.08s;
	user-select: none;
}

/* Die einzige Rückmeldung der Fernbedienungstasten - je Tastenfarbe gab es früher zusätzlich eine eigene
   Hover-Farbe, die aber nur den ohnehin vorhandenen Druckeffekt verdoppelte. */
.remote button:active {
	filter: brightness(0.75);
	transform: scale(0.94);
}

/* ── Grid helpers ── */
.remote .grid-3 {
	display: grid;
	gap: 8px;
	grid-template-columns: repeat(3, 1fr);
}

.remote .grid-4 {
	display: grid;
	gap: 8px;
	grid-template-columns: repeat(4, 1fr);
}

/* ── Dark square buttons (number pad) ── */
.remote .btn-dark {
	background: #3d3d3d;
	border-radius: 10px;
	box-shadow: 0 3px 0 #222, inset 0 1px 0 rgba(255, 255, 255, 0.08);
	color: #e0e0e0;
	width: 100%;
}

.remote .num-pad button {
	font-size: 1rem;
}

/* ── Grey square buttons (nav area) ── */
.remote .btn-grey {
	background: #8a8a8a;
	border-radius: 10px;
	box-shadow: 0 3px 0 #222, inset 0 1px 0 rgba(255, 255, 255, 0.08);
	color: #e0e0e0;
	width: 100%;
}

/* ── Red buttons ── */
.remote .btn-red {
	background: #cc2222;
	border-radius: 10px;
	box-shadow: 0 3px 0 #222, inset 0 1px 0 rgba(255, 255, 255, 0.08);
	color: #fff;
	width: 100%;
}

/* ── Color bar buttons ── */
.remote .btn-color {
	border-radius: 8px;
	box-shadow: 0 3px 0 #222, inset 0 1px 0 rgba(255, 255, 255, 0.08);
	height: 1.5rem;
	width: 100%;
}

.remote #btn-color-red {
	background: #cc2222;
}

.remote #btn-color-green {
	background: #22aa22;
}

.remote #btn-color-yellow {
	background: #ccaa00;
}

.remote #btn-color-blue {
	background: #2244cc;
}

.remote .btn-icon {
	font-size: 1.5rem;
}

.remote .btn-labeled-icon .btn-icon {
	font-size: 1.2rem;
}
.remote .btn-labeled-icon .btn-label {
	color: #aaa;
	font-size: 0.6rem;
}

/* ── Oval/pill buttons (media controls bottom) ── */
.remote .btn-oval {
	background: #3d3d3d;
	border-radius: 20px;
	box-shadow: 0 3px 0 #222, inset 0 1px 0 rgba(255, 255, 255, 0.08);
	color: #c0c0c0;
	font-size: 0.6rem;
	height: 2rem;
	width: 100%;
}

.remote #btn-rec {
	color: #cc2222;
}

.remote .btn-cursor .btn-icon,
.remote .btn-media .btn-icon {
	font-size: 1.2rem;
}

/* ── HELP / PWR top row ── */
.remote .top-row {
	display: flex;
	gap: 8px;
	justify-content: center;
}

.remote .top-row button {
	border-radius: 10px;
	font-size: 0.75rem;
	width: 5rem;
}

.remote #btn-help {
	background: #3d3d3d;
	box-shadow: 0 3px 0 #222, inset 0 1px 0 rgba(255, 255, 255, 0.08);
	color: #e0e0e0;
}

.remote #btn-pwr {
	background: #cc2222;
	box-shadow: 0 3px 0 #222, inset 0 1px 0 rgba(255, 255, 255, 0.08);
	color: #fff;
}

/* ---------------------------------------------------------------------------------------------- */

@media (max-width: 1280px) {

	/* Edit-Form -------------------------------------------------------------------------------- */

	.editForm,
	.editMovieForm,
	.editTimerForm,
	.editAutoTimerForm {
		bottom: 0;
		height: auto;
		left: 0;
		margin: 0;
		max-height: none;
		max-width: none;
		min-width: auto;
		overflow: auto;
		padding: 0.5em 1em 1em 1em;
		position: fixed;
		right: 0;
		top: 4rem;
		width: auto;
		z-index: 10;
	}
}

@media (max-width: 1024px) {
	.sidebar {
		display: none;
	}

	.main-content {
		padding-right: 0;
	}

	/* Hier steht die Schaltflächenreihe einzeilig unter dem Text. Führen beide Sprungknöpfe ins Leere, dürfen sie
	   ganz entfallen - ein Verrutschen der übrigen stört in einer eigenen Zeile niemanden. Einzeln tote Knöpfe
	   bleiben dagegen auch hier stehen, sonst rückte der andere an ihre Stelle.
	   Die Regel hängt bewusst an der Anordnung und nicht am Gerät: Wird die Kopfzeile später ebenfalls einzeilig,
	   gehört sie dorthin mit. */
	.nowPlayingButtons.nowPlayingNavDead .nowPlayingNav {
		display: none;
	}

	/* Hier steht die Reihe einzeilig, senkrecht ist also mehr Luft als im Raster - die Trefferfläche darf nach oben
	   und unten großzügiger ausfallen. Genau hier wird auch mit dem Finger bedient. */
	.nowPlayingButtons > button::after,
	.nowPlayingButtons .toggleMoreFlyout::after {
		inset: -8px -4px;
	}

	.content .dashboard {
		align-items: normal;
		flex-direction: column;
	}

	.content .db-info {
		max-width: none;
		width: 100%;
	}

	/* Actions ---------------------------------------------------------------------------------- */

	.actions .toggleActionFlyout {
		display: inline-block;
	}

	/* Haupt- und "Mehr"-Bereich verschmelzen hier zu einem einzigen senkrechten Menü: Ein Tipp auf "..." zeigt
	   beide untereinander, getrennt durch eine Linie. Vorher waren es zwei Ebenen - das .actionFlyout klappte als
	   waagerechte Icon-Reihe auf und das "Mehr"-Menü darin brauchte einen zweiten Tipp.
	   Ausrichtung deshalb wie bei .actions .moreFlyout (unter dem Button, rechtsbündig) statt wie früher links
	   daneben: Es ist jetzt dasselbe Menü und soll auch so aufklappen. */
	.actions .actionFlyout {
		background-color: var(--surface-raised);
		border: 1px solid var(--control-border);
		border-radius: 10px;
		color: var(--control-text);
		display: none;
		flex-direction: column;
		gap: 0.1em;
		margin-top: 2px;
		padding: 0.4em;
		position: absolute;
		right: 0;
		top: 100%;
		z-index: 8; /* unter den festgehefteten Leisten, siehe .actions .moreFlyout */
	}

	.actions .actionFlyout.open {
		display: flex;
	}

	/* Den gekappten Innenabstand der kompakten Icon-Reihe (.actionsSmall auf der MovieDirs-Seite) zurücknehmen:
	   hier ist es ein Menü mit Textzeilen und sieht aus wie jedes andere. Für die Buttons darin tut das die
	   Regel darunter. */
	.actions.actionsSmall .actionFlyout {
		padding-bottom: 0.4em;
		padding-top: 0.4em;
	}

	/* Menüeinträge wie im "Mehr"-Bereich, siehe ".actions .moreFlyout button, .actions .moreFlyout a".
	   Der "Mehr"-Auslöser bleibt bewusst ausgenommen (statt ihn danach wieder auszublenden): Die zweite Zeile ist
	   nur wegen ".actions.actionsSmall button" nötig und läge mit ihren vier Klassen sonst über jeder schlichten
	   display:none-Regel - der Auslöser stand dann als leerer Eintrag mit im Menü. */
	/* Innenabstand und Abstand in rem statt em: Ein <button> erbt die Schriftgröße nicht (Browservorgabe ~13,3px),
	   ein <a> schon (16px) - dieselbe em-Angabe ergäbe dort andere Pixel, und ein Link stünde sichtbar weiter rechts
	   als die Buttons darüber und darunter (nachgemessen: 12px statt 10px Innenabstand, 9,6px statt 8px Abstand).
	   Mit rem hängt beides an der Wurzelgröße und ist für beide Elementarten gleich. */
	.actions .actionFlyout > button:not(.toggleMoreFlyout),
	.actions .actionFlyout > a,
	.actions.actionsSmall .actionFlyout > button:not(.toggleMoreFlyout) {
		align-items: center;
		color: white;
		display: flex;
		gap: 0.5rem;
		justify-content: flex-start;
		padding: 0.35rem 0.625rem;
		text-align: left;
		text-decoration: none;
		white-space: nowrap;
		width: 100%;
	}

	.actions .actionFlyout > button:active:not([disabled]),
	.actions .actionFlyout > a:active {
		background-color: rgba(102, 153, 221, 0.2);
		border-radius: 6px;
		color: #fff;
	}

	.actions .actionFlyout > button > span,
	.actions .actionFlyout > a > span {
		display: inline;
		font-size: 0.85rem;
	}

	/* Hier steht die Aktion als Text neben dem Symbol - dann muss das Symbol zu ihr passen und nicht zum Zustand,
	   sonst zeigt "Als gesehen markieren" ein durchgestrichenes Auge (siehe ".watchedIconAction" weiter oben). */
	.actions .actionFlyout > button > .watchedIconState {
		display: none;
	}
	.actions .actionFlyout > button > .watchedIconAction {
		display: inline;
	}

	.actions .actionFlyout > button[disabled] > span {
		color: #999;
	}

	/* Der Auslöser des "Mehr"-Menüs entfällt - dessen Einträge stehen ja bereits mit im selben Menü. */
	.actions .actionFlyout > .toggleMoreFlyout {
		display: none;
	}

	/* Das "Mehr"-Menü ist hier kein eigenes Popup mehr, sondern der untere Abschnitt desselben Menüs: kein eigener
	   Rahmen und kein eigener Hintergrund, nur eine Trennlinie nach oben. position:static, damit es unter den
	   Haupteinträgen mitfließt statt sich als Popup darüberzulegen. */
	.actions .actionFlyout > .moreFlyout {
		background-color: transparent;
		border: none;
		border-radius: 0;
		border-top: 1px solid var(--control-border);
		display: flex;
		margin-top: 0.3em;
		padding: 0.3em 0 0;
		position: static;
	}

	/* MovieDirs -------------------------------------------------------------------------------- */

	.movieDirsTable .size,
	.movieDirsTable .length,
	.movieDirsTable .age,
	.movieDirsTable .gotoUrl {
		display: none;
	}

	.movieDirsTable .count,
	.movieDirsTable .unwatched,
	.movieDirsTable .modified {
		font-size: 0.9em;
		white-space: nowrap;
	}

	/* MovieList -------------------------------------------------------------------------------- */

	.movieListTable .type,
	.movieListTable .size {
		display: none;
	}

	/* Timer ------------------------------------------------------------------------------------ */

	.timerTable .time {
		font-size: 0.9em;
	}

	.timerTable .tags,
	.timerTable .autoTimer {
		display: none;
	}
}

@media (min-width: 50rem) {
	.editMovieForm,
	.editTimerForm,
	.editAutoTimerForm {
		flex: 1;
		min-width: 50rem;
		padding-bottom: 0.75em;
		padding-top: 0.75em;
	}
	.editMovieForm {
		padding-top: 2.75em;
	}

	.editMovieForm .form-group:not(.form-group--col1),
	.editTimerForm .form-group:not(.form-group--col1),
	.editAutoTimerForm .form-group:not(.form-group--col1) {
		display: flex;
		margin-bottom: 0.6em;
	}

	.editMovieForm .form-group:not(.form-group--col1) .fieldLabel,
	.editTimerForm .form-group:not(.form-group--col1) .fieldLabel {
		margin-bottom: 0;
		width: 18.5em;
	}

	.editAutoTimerForm .form-group:not(.form-group--col1) .fieldLabel {
		margin-bottom: 0;
		width: 20em;
	}

	.editMovieForm .form-group:not(.form-group--col1) .fieldLabel .fieldLabelIcon,
	.editTimerForm .form-group:not(.form-group--col1) .fieldLabel .fieldLabelIcon,
	.editAutoTimerForm .form-group:not(.form-group--col1) .fieldLabel .fieldLabelIcon {
		float: right;
		margin-right: 1em;
		margin-top: 0.5em;
	}
	.editMovieForm .form-group:not(.form-group--col1) .fieldLabel .fieldLabelIcon + .fieldLabelIcon,
	.editTimerForm .form-group:not(.form-group--col1) .fieldLabel .fieldLabelIcon + .fieldLabelIcon,
	.editAutoTimerForm .form-group:not(.form-group--col1) .fieldLabel .fieldLabelIcon + .fieldLabelIcon {
		margin-right: 0;
	}

	.editMovieForm .form-group:not(.form-group--col1) .form-field,
	.editTimerForm .form-group:not(.form-group--col1) .form-field,
	.editAutoTimerForm .form-group:not(.form-group--col1) .form-field {
		flex: 1;
	}
}

@media (max-width: 640px) {
	header {
		gap: 0.5rem;
		height: 3rem;
		max-width: 100vw;
	}

	.menuBtn {
		height: 3rem;
		width: 3rem;
	}

	.menuBtn .label {
		display: none;
	}

	.globalActions .toggleRemote {
		display: none;
	}
	/* inline-flex statt block, damit die Glyphe mittig bleibt (siehe .globalActions .iconBtn). */
	.globalActions .gotoRemote {
		display: inline-flex;
	}

	/* Auf dem Handy sind die Menüs der Kopfzeile das einzige, was von "Jetzt läuft" zu sehen ist - dort lohnt
	   mehr Luft als die 0.4em ringsum, die für ein Menü zwischen Tabellenzeilen gedacht sind. Links am meisten,
	   weil dort die Texte anfangen. ".actions" wie oben, um nicht mit ".actions .moreFlyout" gleichaufzuliegen.
	   max-width höher als die 80vw von oben: hochkant blieben davon auf einem 390px-Gerät nur 312px, und die
	   Texte wurden mit "..." gekürzt, obwohl rechts noch Platz war. Die restlichen 8vw halten den Abstand zum
	   Rand, den positionFlyout ohnehin erzwingt.
	   font-size etwas größer als die 1rem von oben: hier ist das Menü die einzige Darstellung von "Jetzt läuft",
	   nicht bloß eine Ausweichlösung. Es zieht die em-basierten Zeilen (Beschreibung, Sender) mit hoch. */
	.globalActions .actions .moreFlyout {
		font-size: 1.1rem;
		max-width: 92vw;
		padding: 0.6em 0.5em 0.6em 0.9em;
	}

	/* Titel und Schaltflächen rechnen in rem, folgen der Vergrößerung darüber also nicht von selbst. */
	.globalActions .nowPlayingTitle {
		font-size: 1.05rem;
	}

	.moreFlyout.nowPlayingFlyout .nowPlayingButtons > button,
	.moreFlyout.nowPlayingFlyout .nowPlayingButtons .toggleMoreFlyout {
		font-size: 1.5rem;
	}

	/* Die Zeilen des Tonspur-Menüs ebenso - sie rechnen in rem und blieben sonst als einzige klein.
	   Wichtig: die Größe gehört an beide Zeilenformen, nicht nur an den Text. Ihre Innenabstände rechnen in em,
	   und schon 0.15rem Unterschied zwischen der aktiven Zeile (<span>) und den Schaltflächen verschiebt die
	   Symbolspalte sichtbar gegeneinander. */
	.globalActions .audioTrackFlyout button,
	.globalActions .audioTrackFlyout .audioTrackName {
		font-size: 0.95rem;
	}

	.globalActions .audioTrackFlyout button span {
		font-size: inherit;
	}

	.flyout-menu {
		max-height: calc(var(--vh) * 100 - 3rem);
		top: 3rem;
	}

	.logo {
		font-size: 0.67rem; /* skaliert .testTag proportional zur verkleinerten Höhe mit, siehe dort */
		height: 2rem;
	}

	.globalActions {
		font-size: 0.6em;
		gap: 0;
	}

	main {
		display: block;
		margin-top: 3rem;
		padding: 0 0.5rem;
	}

	.content {
		max-width: 100vw;
		overflow: auto;
		padding: 0.75rem 0 0 0;
	}

	.defaultSelect {
		flex: 1 1 auto;
		min-width: 10rem;
	}

	.select-row {
		display: flex;
		width: calc(100vw - 1rem);
	}

	/* Feste Breite statt nur max-width: <dialog> ist von Haus aus fit-content, dadurch war jeder Dialog auf dem
	   Handy unterschiedlich breit (ein Dialog mit langem Dateipfad fast randfüllend, die Ordnerauswahl dagegen
	   deutlich schmaler). Einheitliche Breite mit 1rem Rand an beiden Seiten: */
	.default-dialog {
		margin: auto;
		max-width: calc(100vw);
		width: calc(100vw - 2rem);
	}

	/* Die Backdrop-Variante legt den Dialog als Flex-Item mittig ins Fenster; ohne dieses Zurücksetzen würde die
	   flex-basis (max-content, siehe .default-dialog-large) die Breite oben überstimmen: */
	.default-dialog-backdrop[open] .default-dialog-large {
		flex: 0 0 auto;
	}

	.content--remote {
		display: none;
	}

	.remoteTextForm {
		display: flex;
		gap: 0.5rem;
		margin-top: 0.5rem;
	}

	.remoteTextForm #remoteTextInput {
		flex: 1 1 auto;
		max-width: none;
		width: inherit;
	}
	
	.remoteTextForm #remoteTextBtn {
		margin: 0;
	}

	.remoteOptions {
		margin: 0.5rem 0;
	}

	.remoteOptions .defaultCheckboxLabel {
		width: 100%;
	}

	.remote {
		margin: 0.75rem auto 0 auto;
		padding: 0.25em 1em;
	}
	
	.remote button {
		height: 2.25rem;
	}

	.remoteFlyout {
		left: calc(50% - 120px);
		margin: 0;
		position: fixed;
		top: 3.75rem;
	}

	#remoteFlyout,
	#remoteFlyout.open {
		display: none;
	}

	/* Statuszeile bei Tabellenseiten ----------------------------------------------------------- */

	.infoBar {
		font-size: 0.9rem;
		gap: 0.5rem 1rem;
		margin: 0 0 1rem 0;
	}

	.infoBar .reloadBtn {
		display: none;
	}

	.countLabel {
		display: none;
	}
	.countIcon {
		display: inline;
	}
	.countWord {
		display: none;
	}
	/* Mit dem Wort davor muss auch sein Zusatz weichen - ohne das stünde in der schmalen Zeile "274 (191 komplett)"
	   ohne das Wort, auf das sich die Klammer bezieht (siehe tmdbmovies.html). */
	.countSub {
		display: none;
	}

	/* Ausnahme Streaming-Portal: Dort bleiben beide stehen. Die Zeile trägt dort nur zwei Angaben statt fünf, der
	   Platz ist also da - und wer die Mediathek nur zum Ansehen benutzt, hat die Zeichen nicht so im Griff wie ein
	   Administrator, der sie täglich sieht. */
	body.portalMode .countWord,
	body.portalMode .countSub {
		display: inline;
	}

	/* Und aus demselben Grund die führende Beschriftung statt ihres Ersatz-Zeichens - dieselbe Vertauschung wie bei
	   der Kategorien-Übersicht unten. Im Portal steht sonst nirgends auf der Seite, wo man ist: Das Seitenmenü fehlt,
	   eine Überschrift gibt es nicht, es bliebe allein die Filmrolle in der Zeile.
	   Beides zusammen wäre verschwendeter Platz, deshalb das Zeichen weg. */
	body.portalMode .countLabel {
		display: inline;
	}

	body.portalMode .countIcon {
		display: none;
	}

	/* Der seitliche Rand des Portals kommt hier wieder weg: Er ersetzt die fehlende Seitenleiste, damit der Inhalt am
	   breiten Bildschirm nicht an der Fensterkante klebt (siehe body.portalMode .main-content). Hochkant auf dem Handy
	   polstert <main> aber schon selbst, und die 1,2rem obendrauf ergaben 27px je Seite statt der 8px, die der
	   Administrator hat - bei 360px Breite ein Siebtel des Bildschirms für nichts. Oben und unten bleibt er.
	   Nur hier drin und damit nur hochkant: Im Querformat ist das Handy breiter als 640px, dort stört er nicht. */
	body.portalMode .main-content {
		padding-left: 0;
		padding-right: 0;
	}

	/* Ausnahme Kategorien-Übersicht: in deren Kopfzeile steht sonst nichts, dort ist auch auf dem Handy Platz für
	   die ausgeschriebene Beschriftung. Das Ersatz-Icon bleibt den gedrängten Kopfzeilen der übrigen Seiten
	   (Aufnahmen, Timer, ...) vorbehalten. */
	.categoriesPage .countLabel {
		display: inline;
	}

	.categoriesPage .countIcon {
		display: none;
	}

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

	table td {
		overflow-wrap: break-word;
		word-break: break-all;
	}

	/* MovieDirs -------------------------------------------------------------------------------- */

	.movieDirsTable .size,
	.movieDirsTable .length,
	.movieDirsTable .modified,
	.movieDirsTable .age,
	.movieDirsTable .gotoUrl {
		display: none;
	}

	/* MovieList -------------------------------------------------------------------------------- */

	.movieListTable .type,
	.movieListTable .size,
	.movieListTable .sender,
	.movieListTable .tags {
		display: none;
	}

	/* Timer ------------------------------------------------------------------------------------ */

	.timerTable .length,
	.timerTable .type,
	.timerTable .sender,
	.timerTable .tags,
	.timerTable .autoTimer {
		display: none;
	}

	/* AutoTimer -------------------------------------------------------------------------------- */

	.autoTimerTable .type,
	.autoTimerTable .filter,
	.autoTimerTable .sender,
	.autoTimerTable .tags,
	.autoTimerTable .timerCount {
		display: none;
	}

	.defaultAccordionItem {
		min-width: auto;
	}

	.textFiltersTable .textFilter input {
		min-width: auto;
	}

	/* EPG -------------------------------------------------------------------------------------- */

	.epgTable .length,
	.epgTable .timer {
		display: none;
	}
	
	/* Edit-Form -------------------------------------------------------------------------------- */

	.editForm,
	.editMovieForm,
	.editTimerForm,
	.editAutoTimerForm {
		top: 3rem;
	}
}

/* TMDB (Filme/Serien) ---------------------------------------------------------------------------- */

/* justify-content entfaellt bewusst: seit .countInfo display:contents traegt, waeren dessen einzelne Angaben
   Flex-Elemente der Leiste und wuerden ueber die volle Breite verteilt. Rechtsbuendig haelt sich die
   Aktionsgruppe ohnehin selbst (siehe .tmdbHeaderActions). */
.tmdbPage .infoBar {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	row-gap: 0.5rem;
}


.tmdbHint {
	color: #d44;
	margin: 0 0 1rem 0;
}

.tmdbEmpty {
	color: #aaa;
	margin: 1rem 0;
}

/* Hinweis auf der Detailseite, dass es den Eintrag bei TMDB nicht mehr gibt (siehe inc/tmdbMeta.html#missingNotice).
   Deutlicher als der schlichte .tmdbHint darüber: Es geht um einen dauerhaften Zustand, der erklärt werden muss, und
   nicht um eine vorübergehende Meldung. Das Zeichen bleibt oben, damit es bei mehrzeiligem Text nicht mitrutscht. */
.tmdbMissingNotice {
	align-items: center;
	background: rgba(221,68,68,0.08);
	border: 1px solid rgba(221,68,68,0.45);
	border-radius: 6px;
	color: var(--text);
	display: flex;
	gap: 0.8rem;
	/* Großzügiger als der Standard: Der Kasten trägt mehrere Zeilen Fließtext, und in einer Meldung, die man nur
	   einmal liest und dann verstanden haben soll, hilft die Luft zwischen den Zeilen spürbar. */
	line-height: 1.55;
	margin: 0 0 1rem 0;
	padding: 0.7rem 0.9rem;
}

/* Die übliche Textfarbe auf dem rötlichen Grund: Ein abgetöntes Rot war darauf kaum zu lesen, reines Weiß dagegen
   grell. Die Warnfarbe trägt allein das Zeichen, das dafür groß genug ist, um die Meldung von weitem einzuordnen. */
.tmdbMissingNotice > i {
	color: #d44;
	flex-shrink: 0;
	font-size: 2.6rem;
}

/* Der Pfad im Hinweis "Der verknüpfte Ordner fehlt": als Pfad kenntlich, ohne dass die Meldung technisch wirkt -
   deshalb nur eine leicht abgesetzte Fläche statt einer echten Schreibmaschinenschrift in anderer Größe. */
.tmdbMissingNotice code {
	background: rgba(255, 255, 255, 0.07);
	border-radius: 4px;
	/* Der doppelte Eintrag ist kein Versehen, sondern der übliche Kniff gegen eine Browser-Eigenheit: Steht dort
	   allein das Schlüsselwort "monospace", rechnen Browser relative Schriftgrößen gegen ihre eigene Vorgabe für
	   Festbreitenschrift (13px) statt gegen den umgebenden Text. Ohne die zweite Angabe hinge die tatsächliche
	   Größe also an einer Browser-Einstellung statt an dieser Zeile.
	   0.9em ergibt die nachgemessenen 14,4px - etwas kleiner als der Fließtext daneben, weil eine
	   Festbreitenschrift bei gleicher Punktgröße breiter baut und sonst aus der Zeile herausspringt. */
	font-family: monospace, monospace;
	font-size: 0.9em;
	padding: 0.05em 0.35em;
	word-break: break-all;
}

/* Die Abhilfe steht mit im Kasten (siehe tmdbMeta.html#dirMissingNotice). Eigene Zeile statt inline im Fließtext:
   Der Knopf ist höher als eine Textzeile und drückte die Zeile, in der er stand, sichtbar auseinander.
   "display: flex" (nicht inline-flex) macht ihn dafür block-artig, "width: fit-content" hält ihn trotzdem so
   schmal wie seine Beschriftung, statt ihn über die ganze Kastenbreite zu ziehen. */
.tmdbMissingNotice .tmdbPillBtn {
	display: flex;
	margin-top: 0.6rem;
	width: fit-content;
}

/* Breadcrumb-Zeile: trägt rechts zusätzlich das "Weitere Aktionen"-Menü der Seite (siehe .tmdbHeaderActions),
   daher Flex statt schlichtem Textabsatz. margin-top sorgt für den Abstand zum Seitenkopf - ohne ihn beginnt der
   Breadcrumb unmittelbar unter der festen Kopfzeile: */
.tmdbBreadcrumb {
	align-items: center;
	color: #aaa;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0.75rem 0 1rem 0;
	min-height: 2rem;
	/* Bewusst kein padding-right: der "..."-Button soll rechts genauso weit vom Rand stehen wie der Zurück-Button
	   links, und beide bündig mit der Inhaltsspalte (Überschrift, Meta-Zeile, Kachelraster). Ein Zusatzabstand nur
	   rechts fiel auf schmalen Bildschirmen als Schieflage auf - dort bringt die Spalte schon beidseitig 8px mit,
	   ein weiteres 1rem ergab 24px rechts gegen 8px links. Die Kopfzeilen der Übersichtsseiten (ohne Breadcrumb)
	   enden ohnehin an derselben Kante. */
}

/* Aktionsgruppe im Seitenkopf - in der Breadcrumb-Zeile nur das "..."-Menü, auf den Übersichtsseiten zusätzlich
   der "Hinzufügen"-Button davor. margin-left:auto hält die Gruppe rechtsbündig, unabhängig davon wie lang der
   Text links daneben ist und ob sie in eine eigene Zeile umbricht: */
.tmdbHeaderActions {
	align-items: center;
	display: inline-flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-left: auto;
}

/* Zurück-Button ganz links: nur das Pfeil-Icon, rund und mit Rahmen, damit der Pfeil klar als Bedienelement
   auftritt statt als Textdekoration am ersten Pfad-Eintrag zu kleben. Er führt eine Ebene nach oben, also auf
   denselben Ort wie der letzte Eintrag des Pfades daneben: */
.tmdbCrumbBack {
	align-items: center;
	background: #1b2b52;
	border: 1px solid #4a70b0;
	border-radius: 50%;
	color: #cfe0f5;
	display: inline-flex;
	flex: none;
	height: 2rem;
	justify-content: center;
	width: 2rem;
}

.tmdbCrumbBack:active {
	background: #2a4383;
	border-color: #7aa0e0;
	color: #fff;
}

/* Der Pfad selbst als <ol> (semantisch eine geordnete Abfolge), ohne die Standard-Einrückung einer Liste: */
.tmdbCrumbTrail {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	list-style: none;
	margin: 0;
	padding: 0;
}

.tmdbCrumbTrail li {
	align-items: center;
	display: inline-flex;
}

/* Trenner als gedrehtes Rahmeneck statt als Icon-Glyphe: so sieht jeder Trenner gleich aus und ist unabhängig
   von der Icon-Schrift - deren Chevron säße auf der Textgrundlinie und damit sichtbar zu tief: */
.tmdbCrumbTrail li + li::before {
	border-right: 2px solid #667;
	border-top: 2px solid #667;
	content: "";
	display: inline-block;
	height: 0.35rem;
	margin: 0 0.6rem;
	/* translateY hebt den Trenner auf die optische Mitte der Versalien: zentriert man ihn auf die Zeilenmitte,
	   endet seine Spitze genau auf der Grundlinie und er wirkt dadurch zu tief: */
	transform: translateY(-1px) rotate(45deg);
	width: 0.35rem;
}

.tmdbCrumbTrail a {
	color: #9ac;
	text-decoration: none;
}

.tmdbCrumbTrail a:active {
	color: #fff;
}

/* Poster-Grid, analog .tiles--grid der Listen-Seite, aber mit Platz für ein hochformatiges Poster: */
.tmdbGrid {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
	margin-top: 1rem;
}

.tmdbTile {
	background: var(--surface);
	border: 1px solid var(--line-subtle);
	border-radius: 8px;
	color: #ddd;
	display: flex;
	flex-direction: column;
	position: relative;
}

/* Bewusst kein overflow:hidden auf .tmdbTile (mehr dazu s.u.) - das würde das .moreFlyout-Dropdown der Kachel
   abschneiden, sobald es über den Kachelrand hinausragt. Stattdessen runden Poster/Platzhalter ihre oberen Ecken
   selbst ab (border-radius passend zu .tmdbTile), der Rest der Kachel braucht kein Clipping. */

.tmdbTile:active {
	box-shadow: 0 6px 18px rgba(0,0,0,0.45);
}

.tmdbPosterLink {
	color: inherit;
	display: block;
	text-decoration: none;
}

.tmdbPoster {
	aspect-ratio: 2 / 3;
	background: var(--page-bg);
	border-radius: 8px 8px 0 0;
	display: block;
	object-fit: cover;
	width: 100%;
}

.tmdbPosterPlaceholder {
	align-items: center;
	aspect-ratio: 2 / 3;
	background: var(--page-bg);
	border-radius: 8px 8px 0 0;
	color: var(--text-faint);
	display: flex;
	font-size: 2.6rem;
	justify-content: center;
	width: 100%;
}

.tmdbTileTitle {
	font-size: 0.85rem;
	font-weight: bold;
	margin: 0.5rem 0.5rem 0.2rem 0.5rem;
	overflow-wrap: anywhere;
}

.tmdbTileMeta {
	color: #aaa;
	font-size: 0.78rem;
	margin: 0 0.5rem 0.5rem 0.5rem;
	margin-top: auto;
}

.tmdbBadges {
	display: flex;
	gap: 0.3rem;
	position: absolute;
	right: 0.4rem;
	top: 0.4rem;
}

/* Warnzeichen mittig im Poster, wenn es den Eintrag bei TMDB nicht mehr gibt (siehe inc/tmdbMeta.html#missingMark).
   Der Rahmen deckt genau den Posterbereich ab - gleiche Breite und gleiches Seitenverhältnis wie .tmdbPoster, oben
   angesetzt -, damit das Zeichen im Bild sitzt und nicht in der Mitte der (je nach Inhalt unterschiedlich hohen)
   Kachel. Vollständig durchlässig für den Zeiger: Das Zeichen sitzt genau dort, wo man die Kachel antippt - finge es
   den Klick ab, käme man von der Postermitte aus nicht mehr auf die Detailseite. Die Erklärung trägt daher der
   Poster-Link als title (siehe inc/tmdbMeta.html#missingTitle). */
.tmdbMissingMark {
	align-items: center;
	aspect-ratio: 2 / 3;
	display: flex;
	justify-content: center;
	left: 0;
	pointer-events: none;
	position: absolute;
	right: 0;
	top: 0;
	z-index: 1;
}

/* Dunkle Scheibe unter dem Zeichen, damit es auch auf einem hellen Poster lesbar bleibt (wie bei .tmdbBadge): */
.tmdbMissingMark > i {
	align-items: center;
	background: rgba(17,17,51,0.85);
	border-radius: 50%;
	color: #d44;
	display: flex;
	font-size: 2.4rem;
	height: 3.4rem;
	justify-content: center;
	width: 3.4rem;
}

/* Archiv-Badge (verknüpft/gesammelt) sitzt immer links oben, unabhängig vom Gesehen-Status (der rechts oben bleibt,
   siehe .tmdbBadges) - eigener Container, da beide gleichzeitig sichtbar sein können: */
.tmdbBadgesLeft {
	display: flex;
	gap: 0.3rem;
	left: 0.4rem;
	position: absolute;
	top: 0.4rem;
}

.tmdbBadge {
	align-items: center;
	background: rgba(17,17,51,0.85);
	border-radius: 50%;
	display: flex;
	height: 1.6rem;
	justify-content: center;
	position: relative; /* Bezug für .tmdbBadgeCount */
	width: 1.6rem;
}

/* Anzahl der verknüpften Aufnahmen, wenn es zu einem Film mehrere Fassungen gibt (siehe tmdbmovies.html) - klein in
   der Ecke des Archiv-Icons, damit dieses erkennbar bleibt: */
.tmdbBadgeCount {
	background: #6af;
	border-radius: 50%;
	bottom: -0.15rem;
	color: var(--page-bg);
	font-size: 0.6rem;
	font-weight: bold;
	line-height: 0.85rem;
	min-width: 0.85rem;
	position: absolute;
	right: -0.15rem;
	text-align: center;
}

.tmdbBadge.watched {
	color: #6c6;
}

.tmdbBadge.collected {
	color: #6af;
}

/* Teilweise gesammelt (noch nicht alle ausgestrahlten Episoden als Aufnahme vorhanden) - grau statt blau, siehe
   tmdbseries.html/tmdbseasons.html: */
.tmdbBadge.collected.partial {
	color: #889;
}

/* Teilweise gesehen (noch nicht alle erschienenen Filme/ausgestrahlten Episoden gesehen) - grau statt grün,
   analog zu .tmdbBadge.collected.partial: */
.tmdbBadge.watched.partial {
	color: #889;
}

/* Eine eigene Notiz liegt vor (siehe inc/tmdbMeta.html, NoteDao) - im selben Gelb wie der Notizblock der
   Detailseite (.tmdbNote): */
.tmdbBadge.note {
	color: #dc8;
}

/* Kennzeichen einer Filmreihe in der Filmübersicht, damit sie dort auf einen Blick von einem einzelnen Film
   unterscheidbar ist (siehe tmdbmovies.html): */
.tmdbBadge.collectionMark {
	color: #cae;
}

/* Die Kachel am Ende der Staffel-Übersicht, die zu den nicht aufgehenden Aufnahmen führt (siehe tmdbseasons.html).
   Bewusst unauffälliger als die Staffeln daneben: sie zeigt keinen Inhalt der Serie, sondern nur einen Hinweis. */
.tmdbTile.tmdbTileMuted {
	background: transparent;
	border-style: dashed;
}

/* Das Fragezeichen füllt die Posterfläche fast aus - es steht hier anstelle eines Bildes, nicht als kleines Symbol
   daneben. Die Obergrenze richtet sich nach der schmalsten Kachel (siehe .tmdbGrid), damit es nicht überläuft. */
.tmdbTile.tmdbTileMuted .tmdbPosterPlaceholder {
	background: transparent;
	font-size: 8rem;
}

.tmdbTile.tmdbTileMuted .tmdbTileTitle {
	text-align: center;
}

/* Die Zahlen sollen bündig untereinander stehen, der Block als Ganzes aber mittig unter dem Fragezeichen: deshalb
   die Breite auf den Inhalt schrumpfen und diesen Block zentrieren, statt den Text selbst zu zentrieren. */
.tmdbTile.tmdbTileMuted .tmdbTileMeta {
	margin-left: auto;
	margin-right: auto;
	width: fit-content;
}

.tmdbTile.tmdbTileMuted .tmdbTileMeta span {
	display: block;
}

/* Ein Film einer Filmreihe, der (noch) nicht in der eigenen Sammlung ist - gedämpft, damit die Lücken der Reihe
   sofort erkennbar sind (siehe tmdbcollection.html): */
.tmdbTile.notAdded {
	opacity: 0.55;
}

/* Wie beim Tooltip bewusst :hover statt :active: Auf Touch-Geräten bleibt die Kachel nach dem Antippen hell
   stehen, und erst dann ist "Übernehmen" gut genug zu erkennen, um es zu treffen. Mit :active wäre sie nur
   hell, solange der Finger liegt - man müsste blind auf einen gedämpften Knopf zielen. */
.tmdbTile.notAdded:hover {
	opacity: 1;
}

/* Etwas kleiner und enger gesetzt als die übrigen Kachel-Links: "Übernehmen" ist die längste Beschriftung, die in
   einer Kachelzeile vorkommt, und stünde sonst als einzige nicht mehr neben dem TMDB-Link (siehe .tmdbTileLinks). */
.tmdbAddPartBtn {
	align-items: center;
	background: transparent;
	border: none;
	color: #9ac;
	cursor: pointer;
	display: inline-flex;
	font-family: inherit;
	font-size: 0.75rem;
	gap: 0.125rem;
	margin-left: auto;
	padding: 0;
}

.tmdbAddPartBtn:active:not([disabled]) {
	color: #fff;
}

.tmdbProgress {
	background: var(--page-bg);
	border-radius: 3px;
	height: 0.35rem;
	margin: 0 0.5rem 0.5rem 0.5rem;
	overflow: hidden;
}

/* "Gesehen"-Balken, in Grün passend zum Gesehen-Icon (.tmdbBadge.watched): */
.tmdbProgressFill {
	background: #6c6;
	height: 100%;
}

/* Umhüllung, die nur den Tooltip eines Fortschrittsbalkens trägt (siehe tmdbmovies.html): .tmdbProgress selbst braucht
   overflow:hidden, damit der Füllbalken den runden Ecken folgt - das würde die Tooltip-Blase abschneiden. Der
   Innenabstand vergrößert zugleich die Hover-Fläche des nur 0.35rem hohen Balkens; dafür rückt dessen Abstand hierher,
   sodass die Kachel gleich hoch bleibt. */
.tmdbProgressTip {
	padding: 0.15rem 0;
}

.tmdbProgressTip .tmdbProgress {
	margin-bottom: 0.2rem;
}

/* Balken über dem "gesehen"-Balken: zeigt den Anteil ausgestrahlter Episoden, zu denen eine Aufnahme
   existiert ("gesammelt"), in Blau passend zum Archiv-Icon (.tmdbBadge.collected) - immer sichtbar (auch bei 0%),
   damit alle Kacheln auf einer Höhe bleiben (siehe tmdbseries.html/tmdbseasons.html): */
.tmdbProgressFillCollected {
	background: #6af;
}

.tmdbTileActions {
	align-items: center;
	display: flex;
	gap: 0.4rem;
	justify-content: space-between;
	padding: 0 0.4rem 0.5rem 0.4rem;
}

.tmdbTileActions button {
	align-items: center;
	background: transparent;
	border: none;
	color: #ddd;
	cursor: pointer;
	display: inline-flex;
	font-size: 1.1rem;
	padding: 0.2rem;
}

.tmdbTileActions button:active {
	color: #fff;
}

.tmdbNextEpisodeLabel {
	font-size: 0.75rem;
	margin-left: 0.3rem;
}

/* "Weitere Aktionen"-Menü auf Film-/Serien-Kacheln (bei Filmen in .tmdbTileLinks statt hier, siehe dort), immer an den
   rechten Rand der Zeile gedrückt - funktioniert unabhängig vom umgebenden justify-content: */
.tmdbTileMoreActions {
	margin-left: auto;
}

/* .tmdbPillBtn ist der Alias für "sieht aus wie eine Schaltfläche mit Beschriftung, ist aber keine .defaultBtn"
   (etwa im Such-Dialog). Die Optik selbst kommt aus .defaultBtn, siehe dort. */
.tmdbPillBtn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-family: inherit;
	font-size: 0.9rem;
	gap: 0.35rem;
	height: var(--control-height);
	justify-content: center;
	padding: 0 0.9rem;
}

.tmdbPillBtn:active:not([disabled]) {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

.tmdbPillBtn i {
	font-size: 1.1rem;
}

/* Im Seitenkopf sitzen die Schaltflächen in einer Flex-Zeile, die den Abstand über gap regelt - der eigene
   Außenabstand von .defaultBtn würde sie gegen den "..."-Button daneben um 2px versetzen: */
.tmdbHeaderActions .defaultBtn {
	margin: 0;
}

/* Das "..."-Menü der Seitenköpfe: rund und so breit wie hoch, wie die Zurück-/Blätter-Buttons. Der Selektor muss
   .actions mitnehmen, weil das umgebende <span class="actions"> ".actions button { background: transparent;
   border: none }" mitbringt und eine einzelne Klassenregel das sonst nicht überstimmt. */
.actions .tmdbBurgerBtn,
.tmdbBurgerBtn {
	align-items: center;
	background-color: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: 50%;
	color: var(--control-text);
	cursor: pointer;
	display: inline-flex;
	font-size: 1.1rem;
	height: var(--control-height);
	justify-content: center;
	margin: 0;
	padding: 0;
	width: var(--control-height);
}

.actions .tmdbBurgerBtn:active,
.tmdbBurgerBtn:active {
	background-color: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

/* Suche (Dialoge zum Hinzufügen) ------------------------------------------------------------------ */

.tmdbSearchRow {
	align-items: center;
	display: flex;
	gap: 0.5rem;
	margin-bottom: 0.75rem;
}

/* Eingabefeld und Suchen-Button exakt gleich hoch. Die Schaltfläche bringt ihre Höhe inzwischen selbst mit
   (siehe .defaultBtn), das Feld daneben muss nur mitziehen - align-items/align-self: stretch hilft hier nicht,
   ein <button> streckt sich als Flex-Item nicht mit (nachgemessen). */
.tmdbSearchRow input {
	height: var(--control-height);
}

/* min-width: 0 ist zwingend: ein <input> hat als Flex-Item die Vorgabe min-width:auto, also min-content - das
   entspricht der Default-Feldbreite von rund 20 Zeichen. Ohne die Regel schrumpft das Feld trotz flex:1 nicht
   weiter, und auf schmalen Displays schiebt es stattdessen den "Suchen"-Button aus dem Dialog heraus: */
.tmdbSearchRow input {
	flex: 1;
	min-width: 0;
}

/* Der Suchen-Button zeigt hier nur die Lupe. margin: 0 hebt den Standardabstand der Schaltflächen auf - er zählt
   bei align-items:center zur Boxhöhe und würde den Button gegenüber dem Eingabefeld um 2px nach oben versetzen.
   Ein Nur-Icon-Button ist rund, wie überall in der Anwendung: */
.tmdbSearchRow .defaultBtn {
	border-radius: 50%;
	margin: 0;
	padding: 0;
	width: var(--control-height);
}

/*
 * grid-auto-rows/align-content sind nötig, seit der Dialog die volle Fensterhöhe nutzt (siehe .default-dialog-tall):
 * dadurch hat der Grid eine feste Höhe, und mit den Standardwerten (auto-Zeilen + align-content:stretch) richtet sich
 * die Zeilenhöhe nach dem Container statt nach dem Inhalt - die Kacheln wurden dann gestaucht (quadratisches Poster,
 * unten abgeschnitten). max-content bindet die Zeilenhöhe an den Inhalt, start füllt von oben statt zu dehnen.
 */
.tmdbSearchResults {
	align-content: start;
	display: grid;
	gap: 0.75rem;
	grid-auto-rows: max-content;
	grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
	max-height: 60vh;
	overflow-y: auto;
}

.tmdbSearchResult {
	background: var(--surface);
	border-radius: 8px;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	position: relative;
}

.tmdbSearchResultAdded,
.tmdbSearchResultCollection {
	align-items: center;
	background: rgba(17,17,51,0.85);
	border-radius: 50%;
	color: #6c6;
	display: flex;
	height: 1.6rem;
	justify-content: center;
	position: absolute;
	right: 0.4rem;
	top: 0.4rem;
	width: 1.6rem;
}

/* Kennzeichen einer Filmreihe unter den Suchtreffern - links oben, damit es neben dem "bereits in der Sammlung"-Haken
   rechts Platz hat, und lila wie überall im Bereich (siehe .tmdbBadge.collectionMark): */
.tmdbSearchResultCollection {
	color: #cae;
	left: 0.4rem;
	right: auto;
}

/* flex:none, damit das Poster in einer knappen Kachel nie gestaucht wird und sein 2:3-Format behält. Seit das Poster
   in einer Schaltfläche steckt (siehe .tmdbPosterBtn), ist diese das Flex-Kind und braucht es ebenfalls: */
.tmdbSearchResult .tmdbPosterBtn,
.tmdbSearchResult .tmdbPoster,
.tmdbSearchResult .tmdbPosterPlaceholder {
	aspect-ratio: 2 / 3;
	flex: none;
}

.tmdbSearchResultTitle {
	flex: 1;
	font-size: 0.8rem;
	margin: 0.4rem 0.4rem 0.2rem 0.4rem;
	overflow-wrap: anywhere;
}

.tmdbSearchResultBtn {
	margin: 0 0.4rem 0.4rem 0.4rem;
}

/* Zusatzangabe unter dem Titel einer Filmreihen-Trefferkarte ("3/5 in der Sammlung"): */
.tmdbSearchResultMeta {
	color: #aaa;
	font-size: 0.75rem;
	margin: 0 0.4rem 0.3rem 0.4rem;
}

/* Kopfzeile der aufgeklappten Filmreihe im Such-Dialog: Zurück-Button, Name, "Alle übernehmen" rechts. */
.tmdbSearchCollectionBar {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin: 0 0 0.75rem 0;
}

/* Muss sein: display aus der Regel darüber schlägt sonst das hidden-Attribut, mit dem das JS die Zeile ausblendet -
   die Kopfzeile stand dann auch über der gewöhnlichen Trefferliste, nur ohne Namen. */
.tmdbSearchCollectionBar[hidden] {
	display: none;
}

.tmdbSearchCollectionTitle {
	align-items: center;
	color: #cfe0f5;
	display: inline-flex;
	font-weight: bold;
	gap: 0.35rem;
	overflow-wrap: anywhere;
}

#tmdbSearchAddAll {
	margin-left: auto;
}

/* Ohne :disabled-Variante: Der "hinzugefügt"-Knopf war früher gesperrt, führt jetzt aber auf die Detailseite in der
   Mediathek (siehe markAsAdded in tmdbCommon.js) und ist damit nie mehr deaktiviert. */
.tmdbSearchResultBtn.added {
	background-color: #1e5631;
	border-color: #1e5631;
	color: #dfffe0;
}

/* Der Knopf sieht wie eine reine Zustandsanzeige aus, ist aber ein Sprungziel. Ohne eigene Hover-Farbe bliebe er
   beim Überfahren völlig stumm - den Mauszeiger bringt .defaultBtn ohnehin mit. */
.tmdbSearchResultBtn.added:hover {
	background-color: #27703f;
	border-color: #27703f;
}

.tmdbSearchResultBtn.added i {
	color: #7ee787;
}

.tmdbSearchResult .tmdbRating {
	font-size: 0.78rem;
	margin: 0 0.4rem 0.3rem 0.4rem;
}

/* Ordner-Scan: Review-Dialog für uneindeutige Treffer ---------------------------------------------- */

/* Kopfzeile des Scan-Ergebnisses: Texte links, "Fertig" rechts daneben statt in einer Fußzeile darunter. Das spart
   die Höhe der Fußzeile für die Trefferliste und hält die Schaltfläche erreichbar, ohne ans Listenende zu scrollen.
   Oben ausgerichtet, damit sie bei mehrzeiligem Text nicht mittig mitwandert. */
.tmdbScanReviewBar {
	align-items: flex-start;
	display: flex;
	gap: 1rem;
	margin-bottom: 0.75rem;
}

.tmdbScanReviewTexts {
	flex: 1;
	min-width: 0;
}

.tmdbScanReviewBar .defaultBtn {
	flex: none;
	margin: 0;
}

.tmdbScanReviewSummary {
	color: #ccc;
	font-weight: bold;
	margin: 0 0 0.25rem 0;
}

/* Den Abstand zur Liste gibt die Leiste vor (siehe .tmdbScanReviewBar), sonst zählte er doppelt. */
.tmdbScanReviewHint {
	color: #aaa;
	font-size: 0.85rem;
	margin: 0;
}

.tmdbScanReviewList {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	max-height: 60vh;
	overflow-y: auto;
}

.tmdbScanReviewItem {
	border-top: 1px solid var(--line-subtle);
	padding-top: 0.75rem;
}

.tmdbScanReviewItemTitle {
	align-items: center;
	display: flex;
	font-weight: bold;
	gap: 0.4rem;
}

.tmdbScanReviewItemInfoBtn {
	background: transparent;
	border: none;
	color: inherit;
	cursor: pointer;
	font-size: 1rem;
	padding: 0;
}

.tmdbScanReviewItemInfoBtn:active {
	color: #fff;
}

.tmdbScanReviewItemDesc {
	color: #ccc;
	font-size: 0.82rem;
	margin-top: 0.15rem;
}

.tmdbScanReviewItemLength {
	color: #aaa;
	font-size: 0.78rem;
	margin-top: 0.15rem;
}

.tmdbScanReviewItemPath {
	color: #889;
	font-size: 0.78rem;
	margin-bottom: 0.5rem;
	margin-top: 0.15rem;
	overflow-wrap: anywhere;
}

.tmdbScanReviewCandidates {
	grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
}

.tmdbScanReviewManualBtn {
	margin-top: 0.5rem;
}

/* Das Poster einer Trefferkarte ist die Schaltfläche fürs Detail-Popup (siehe posterButton in tmdbCommon.js) - die
   Fläche selbst ist der Knopf, deshalb ohne eigene Optik. */
.tmdbPosterBtn {
	background: none;
	border: none;
	cursor: pointer;
	display: block;
	padding: 0;
	width: 100%;
}

/* Bewusst nur das Bild: der Platzhalter daneben zentriert sein Symbol per display:flex (siehe .tmdbPosterPlaceholder,
   bringt auch width:100% schon mit) - ein display:block von hier aus nähme ihm die Zentrierung. */
.tmdbPosterBtn .tmdbPoster {
	display: block;
	width: 100%;
}

.tmdbScanReviewItem.done {
	align-items: center;
	color: #6c6;
	display: flex;
	gap: 0.4rem;
}

/* Detail-Popup hinter dem Poster einer Trefferkarte (siehe showTmdbDetailPopup in tmdbCommon.js) ---

   Breit angelegt, damit Poster und Text nebeneinander Platz haben - aber bewusst nur so hoch wie sein Inhalt statt
   wie .default-dialog-tall stets fensterhoch: bei einem kurzen Eintrag stünde darunter sonst viel Leerraum. Erst bei
   langem Inhalt (Filmreihe mit vielen Filmen) wächst er bis kurz vor den Fensterrand, dann scrollt .tmdbDetailBody.
   Die eigene max-width hebt die schmale Vorgabe von .default-dialog auf (dort min(40rem, 100%)). */
.tmdbDetailDialog {
	display: flex;
	flex-direction: column;
	max-height: calc(100% - 2rem);
	max-width: calc(100% - 2rem);
	width: 64rem;
}

.tmdbDetailDialog .default-dialog-content {
	display: flex;
	flex-direction: column;
	min-height: 0;
	overflow: hidden;
}

/* Poster links, Angaben rechts; gescrollt wird der ganze Block, weil bei einer Filmreihe die Filmliste unter der
   Inhaltsangabe deutlich länger werden kann als das Poster hoch ist. */
.tmdbDetailBody {
	display: flex;
	flex: 1;
	gap: 1.2rem;
	min-height: 0;
	overflow-y: auto;
}

/* align-self, damit das Poster seine Höhe aus dem Bild bezieht statt (als Flex-Kind) auf die Höhe der Textspalte
   gestreckt zu werden - bei einer Filmreihe mit vielen Filmen wäre es sonst arg in die Länge gezogen. sticky hält es
   beim Scrollen dieser langen Liste im Blick. */
.tmdbDetailPoster {
	align-self: flex-start;
	border-radius: 8px;
	flex: none;
	position: sticky;
	top: 0;
	width: 15rem;
}

/* min-width:0, damit lange Wörter der Inhaltsangabe die Spalte nicht aufziehen statt umzubrechen: */
.tmdbDetailInfo {
	min-width: 0;
}

/* Gleichmäßiger Abstand zwischen allen Blöcken der Textspalte (Meta-Zeile, Genres, Tagline, Regie, Inhaltsangabe,
   Filmliste). Die Bausteine bringen von den Detailseiten teils gar keinen eigenen Abstand mit (die Meta-Zeile) und
   teils nur einen knappen - dort verteilen sie sich über die ganze Seitenbreite, hier stehen sie eng untereinander
   und klebten sonst aneinander. Der Abstand wird deshalb einheitlich hier gesetzt: oben statt unten, damit unter dem
   letzten Block kein Rest bleibt.
   Bewusst mit zwei Klassen, um die Vorgaben der Bausteine zu überstimmen - .tmdbOverview & Co. stehen weiter unten in
   dieser Datei und gewännen bei gleicher Spezifität. */
.tmdbDetailBody .tmdbDetailInfo > * {
	margin-bottom: 0;
	margin-top: 0.9rem;
}

.tmdbDetailBody .tmdbDetailInfo > :first-child {
	margin-top: 0;
}

.tmdbDetailMeta {
	gap: 0.5rem;
}

/* Trennpunkt zwischen den Angaben der Meta-Zeile - als eigenes Element, damit er beim Umbruch nicht am Zeilenanfang
   landet und mit dem gap der Zeile mitgeht: */
.tmdbDetailSep {
	color: #789;
}

.tmdbDetailCredit {
	color: #bbb;
}

/* Die Filme einer Filmreihe: sie treten an die Stelle der Angaben, die TMDB auf Reihen-Ebene nicht kennt. */
.tmdbDetailParts {
	list-style: none;
	padding: 0;
}

.tmdbDetailParts li {
	border-top: 1px solid var(--line-subtle);
	padding: 0.35rem 0;
}

.tmdbDetailPartYear {
	color: #9ab;
}

/* Auf schmalen Bildschirmen (Handy) übereinander, sonst bliebe für den Text neben dem Poster zu wenig übrig: */
@media (max-width: 640px) {
	.tmdbDetailBody {
		flex-direction: column;
	}

	/* Übereinander ist ein mitscrollendes Poster richtig - festgeheftet verdeckte es sonst den Text darunter: */
	.tmdbDetailPoster {
		align-self: center;
		position: static;
		width: min(60%, 12rem);
	}
}

/* Verknüpfen-Dialog (Suche über bestehende Aufnahmen bzw. Verzeichnisse) -------------------------- */

.tmdbLinkResults {
	max-height: 50vh;
	overflow-y: auto;
}

.tmdbLinkResult {
	border-bottom: 1px solid var(--line-subtle);
	cursor: pointer;
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	padding: 0.5rem 0.2rem;
}

.tmdbLinkResult:active {
	background: var(--surface);
}

/* Deutlich abgesetzte Auswahl: der frühere Hintergrund lag nur einen Blauwert neben dem des Dialogs und war
   praktisch nicht zu erkennen. Die Auswahl trägt deshalb dieselbe Füllung wie ein aktives Segment; die
   Zusatzzeilen werden mit aufgehellt, da ihr Grau auf dem helleren Untergrund abfiele: */
.tmdbLinkResult.active {
	background: var(--control-bg-hover);
	color: var(--control-text-hover);
}

.tmdbLinkResult.active .tmdbLinkResultDesc,
.tmdbLinkResult.active .tmdbLinkResultPath {
	color: #dde;
}

.tmdbLinkResultDesc {
	color: #99a;
	display: block;
	font-size: 0.78rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.tmdbLinkResultPath {
	color: #778;
	display: block;
	font-size: 0.72rem;
	overflow-wrap: anywhere;
}

/* Verknüpfen-Dialog: "Ausgewählt"-Info + Radiobuttons stehen untereinander statt nebeneinander zu kleben ----- */

.tmdbLinkWinnerGroup {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.tmdbLinkSelectedInfo {
	margin: 0;
}

.tmdbLinkWinnerOption {
	align-items: center;
	display: flex;
	gap: 0.4rem;
}

/* Staffel/Episoden-Detailseiten ------------------------------------------------------------------- */

.tmdbOverview {
	color: #ccc;
	line-height: 1.6;
	margin: 0 0 1rem 0;
	max-width: 90rem;
}

/*
 * Inhaltsangabe und eigene Notiz (siehe inc/tmdbMeta.html#overviewWithNote): Ist daneben genug Platz, steht die Notiz
 * als Zettel rechts neben dem Text und bekommt dort ihre gelbe Kopfzeile; sonst steht sie schlicht darunter.
 *
 * Gemessen wird der vorhandene Platz, nicht die Fensterbreite (@container statt @media): Wie breit die Inhaltsangabe
 * ist, hängt nicht am Fenster, sondern an der Seite - auf der Filmdetailseite steht sie neben dem Poster, auf der
 * Serien- und Filmreihenseite über die volle Breite.
 *
 * Bewusst eine Container-Abfrage statt eines Umbruchs per flex-wrap: Der Umbruchpunkt von flex-wrap hängt auch an der
 * Textlänge der Notiz und ist damit nicht abfragbar - die Kopfzeile erschiene dann in einem schmalen Bereich, obwohl
 * der Kasten längst unter der Inhaltsangabe steht.
 */
.tmdbOverviewRow {
	container-type: inline-size;
}

.tmdbOverviewRowInner {
	align-items: flex-start;
	display: flex;
	flex-direction: column;
}

/* 46rem = Inhaltsangabe (mind. ~23rem) + Abstand + Notiz (höchstens 22rem): darunter bliebe für den Text zu wenig. */
@container (min-width: 46rem) {
	.tmdbOverviewRowInner {
		flex-direction: row;
		gap: 0 1.4rem;
	}

	/* Feste Basis statt "auto": Mit auto wäre die Basis die Breite des Textes in einer einzigen Zeile, die Zeile also
	   weit überfüllt - beide Spalten würden dann anteilig geschrumpft und die Notiz landete auf Wortbreite. */
	.tmdbOverviewRowInner .tmdbOverview {
		flex: 1 1 24rem;
		min-width: 0;
	}

	/* Schmaler als der Kasten für sich allein (50rem): Neben dem Fließtext soll er ein Zettel bleiben und nicht die
	   halbe Zeile einnehmen. width: fit-content aus .tmdbNote gilt weiter - kurze Notizen bleiben kurz. */
	.tmdbOverviewRowInner .tmdbNote {
		/* Nicht schrumpfen: Der Zettel behält die Breite seines Inhalts, Platz gibt die Textspalte ab. */
		flex: 0 0 auto;
		max-width: min(22rem, 100%);
	}

	/* Zettel-Optik: Kopfzeile über dem Text statt Zeichen daneben. Der linke Balken entfällt dabei - die
	   Kennzeichnung trägt jetzt die Kopfzeile, beides zusammen wäre doppelt gemoppelt. */
	.tmdbOverviewRowInner .tmdbNote {
		border-left-width: 1px;
		display: block;
		/* Damit die Kopfzeile die abgerundeten Ecken des Kastens nicht überzeichnet: */
		overflow: hidden;
		padding: 0;
	}

	/* Alle Regeln hier laufen über .tmdbNote, um die Grundregeln zu überstimmen: Eine Container-Abfrage erhöht die
	   Spezifität nicht, und die Grundregeln stehen weiter unten in dieser Datei - bei Gleichstand gewännen sie. */
	.tmdbOverviewRowInner .tmdbNote > .tmdbNoteHeader {
		align-items: center;
		background: #dc8;
		/* Dunkel auf Gelb - das sonst gelbe Zeichen wäre auf der eigenen Farbe unsichtbar: */
		color: var(--surface-dialog);
		display: flex;
		/* Ausdrücklich auf Notiztextgröße: Ohne die Angabe erbte die Aufschrift die 1,5rem der Grundregel, die dort
		   nur das allein stehende Zeichen groß macht. */
		font-size: 0.9rem;
		font-weight: 700;
		gap: 0.4rem;
		/* Etwas weiter gesperrt als zuvor: Versalien stehen sonst zu gedrängt. */
		letter-spacing: 0.06em;
		/* Ohne die geerbte Zeilenhöhe von 1,55: Sie bläht den Kasten der Aufschrift auf, was das senkrechte
		   Ausrichten gegen das Zeichen daneben verfälscht. */
		line-height: 1;
		margin: 0;
		/* Oben etwas mehr, unten entsprechend weniger: Das rückt Aufschrift und Zeichen gemeinsam um rund 1,5px nach
		   unten, wo sie optisch mittig sitzen, und lässt die Höhe der Zeile unverändert. Versalien brauchen das, weil
		   sie den Raum der Unterlängen nicht ausfüllen und dadurch zu hoch wirken. */
		padding: 0.4rem 0.7rem 0.2rem;
		text-transform: uppercase;
	}

	/* Nur eine Winzigkeit größer als die Schrift daneben: Zeichen wirken bei gleicher Größe optisch kleiner als
	   Buchstaben. Deutlich größer wäre falsch - die Kopfzeile soll den Kasten anschreiben, nicht ihn beherrschen. */
	/* Das Zeichen steht rechts außen, die Aufschrift links - wie die Schaltflächen in den Dialog-Kopfzeilen.
	   order statt umgestellter Auszeichnung, damit der schmale Zustand unverändert mit dem Zeichen beginnt. */
	.tmdbOverviewRowInner .tmdbNote > .tmdbNoteHeader > .tmdbNoteEditBtn {
		font-size: 1.1rem;
		margin-left: auto;
		margin-top: 0;
		order: 1;
	}

	/* Die Kette bis .tmdbNote ist nötig, um die Ausblendung des Wortes im Grundzustand zu überstimmen - eine
	   Container-Abfrage erhöht die Spezifität nicht. */
	.tmdbOverviewRowInner .tmdbNote > .tmdbNoteHeader > span {
		display: inline;
	}

	.tmdbOverviewRowInner .tmdbNote > .tmdbNoteText {
		display: block;
		padding: 0.6rem 0.8rem;
	}
}

/* Die eigene Notiz einer Detailseite (siehe inc/tmdbMeta.html#note). Abgesetzt von der Inhaltsangabe darüber, damit
   erkennbar bleibt, dass der Text nicht von TMDB stammt; pre-wrap erhält die eingegebenen Zeilenumbrüche. */
.tmdbNote {
	/* Getönte Fläche mit Rahmen wie beim .tmdbMissingNotice, nur in Gelb: Ein bloßer Randstrich reichte nicht - die
	   Notiz stand direkt unter der Inhaltsangabe und sah aus wie ein weiterer Absatz davon. */
	background: rgba(221,204,136,0.10);
	border: 1px solid rgba(221,204,136,0.45);
	/* Kräftiger an der Seite, das gibt dem Kasten die Anmutung eines angehefteten Zettels: */
	border-left-width: 4px;
	border-radius: 6px;
	color: var(--text);
	display: flex;
	gap: 0.8rem;
	line-height: 1.55;
	margin: 0 0 1rem 0;
	padding: 0.7rem 0.9rem;
	/* Nur so breit wie ihr Inhalt: Eine Notiz ist meist ein Satz, über die volle Spaltenbreite gezogen bestand der
	   Kasten überwiegend aus Leerraum. Längerer Text bricht an der Maximalbreite um. */
	max-width: min(50rem, 100%);
	width: fit-content;
}

/* Steht die Notiz unter der Inhaltsangabe, schrumpft die Kopfzeile auf ihr Zeichen zusammen: Ein Balken mit der
   Aufschrift "Notiz" wäre über einem einzeiligen Satz mehr Rahmen als Inhalt (die Zettel-Optik daneben steht im
   @container-Block weiter oben). */
.tmdbNote > .tmdbNoteHeader {
	color: #dc8;
	flex-shrink: 0;
	font-size: 1.5rem;
	line-height: 1;
	/* Auf die erste Textzeile ausgerichtet, nicht auf die Mitte eines mehrzeiligen Blocks: */
	margin-top: 0.1rem;
}

.tmdbNote > .tmdbNoteHeader > span {
	display: none;
}

/* Das Zeichen ist zugleich die Schaltfläche zum Bearbeiten. Flächenlos wie in der Seiten-Kopfzeile (.iconBtn), und
   Farbe wie Größe geerbt, damit es in beiden Zuständen genauso aussieht wie zuvor das reine Zeichen. */
.tmdbNoteEditBtn {
	color: inherit;
	font-size: inherit;
	line-height: 1;
	padding: 0;
}

/* Die eingegebenen Zeilenumbrüche bleiben erhalten - am Text selbst, nicht am Kasten, damit die Auszeichnung nicht
   auch für den Abstand zwischen Zeichen und Text gilt: */
.tmdbNoteText {
	white-space: pre-wrap;
}

/* Film-Detailseite -------------------------------------------------------------------------------- */

/* Der eigene Abstand nach oben sorgt dafür, dass der Poster-Block immer gleich weit vom Vorhergehenden absteht -
   egal ob darüber der Titel, der Originaltitel oder die Tagline endet. Diese bringen unterschiedlich große untere
   Abstände mit (die Überschrift rund 20px, die Tagline nur 8), und da benachbarte Abstände verschmelzen statt sich
   zu addieren, gewinnt immer der größere von beiden. Auf der Serien-Detailseite übernimmt das die .infoBar. */
.tmdbMovieDetailHero {
	align-items: flex-start;
	display: flex;
	flex-wrap: wrap;
	gap: 1.2rem;
	margin-top: 1.25rem;
}

/* Anders als in der Kachel steht das Poster hier fest neben dem Text, statt die volle Breite zu füllen. Die Umhüllung
   trägt die Breite und ist zugleich der Bezugspunkt für die Kennzeichen (.tmdbBadges/.tmdbBadgesLeft sind absolut
   positioniert): */
.tmdbMovieDetailPoster {
	flex: none;
	position: relative;
	width: 13rem;
}

.tmdbMovieDetailHero .tmdbPoster,
.tmdbMovieDetailHero .tmdbPosterPlaceholder {
	border-radius: 8px;
	width: 100%;
}

.tmdbMovieDetailInfo {
	flex: 1 1 20rem;
}

/* Ohne diese Korrektur klafft hier eine Lücke zum Posterrand, weil .infoBar sonst überall einen eigenen
   Abstand nach oben zum vorangehenden Element mitbringt - hier ist es aber das erste Element der Spalte: */
.tmdbMovieDetailInfo .infoBar {
	margin-top: 0;
}

/* Je verknüpfter Aufnahme eine Schaltfläche mit ihrer Bezeichnung ("21:9, o. Nachspann"). Bewusst kompakt als Chips
   nebeneinander statt als Karten untereinander: mehrere Fassungen desselben Films sind der Sonderfall und sollen die
   Seite nicht dominieren. */
.tmdbRecordingChips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}

.tmdbRecordingChip {
	align-items: center;
	background: #1b2b52;
	border: 1px solid #4a70b0;
	border-radius: 999px;
	color: #cfe0f5;
	display: inline-flex;
	font-family: inherit;
	gap: 0.2rem;
	padding: 0.15rem 0.3rem 0.15rem 0.8rem;
}

.tmdbRecordingChip:active {
	background: #2a4383;
	border-color: #7aa0e0;
}

.tmdbRecordingChip .playMovie,
.tmdbRecordingChip .tmdbRecordingMissing {
	align-items: center;
	background: transparent;
	border: none;
	color: inherit;
	display: inline-flex;
	font-family: inherit;
	font-size: 0.82rem;
	gap: 0.35rem;
	padding: 0.3rem 0;
}

.tmdbRecordingChip .playMovie {
	cursor: pointer;
}

/* Trennlinie zwischen dem Abspielen-Teil und dem "..."-Menü, wie bei einer zweigeteilten Schaltfläche üblich. In der
   Rahmenfarbe des Chips, damit kein zweiter Blauton entsteht.
   Die beiden Abstände sind bewusst ungleich notiert, damit die Linie optisch mittig steht: rechts kommt zum Polster
   noch das Innenpolster des "..."-Buttons (0,1rem, siehe .actions.actionsSmall button) und die Luft hinzu, die das
   Punkte-Symbol in seiner em-Box lässt (bei 1,2rem gut 3px) - links dagegen nur der Chip-Abstand (gap 0,2rem), denn
   der Text steht bündig an seiner Kante. Nachgemessen ergibt das rund 7px auf jeder Seite. */
.tmdbRecordingChip .actions {
	border-left: 1px solid #4a70b0;
	margin-left: 0.25rem;
	padding-left: 0.15rem;
}

.tmdbRecordingChip:active .actions {
	border-left-color: #7aa0e0;
}

.tmdbRecordingChip .playMovie:active {
	color: #fff;
}

/* Verwaiste Verknüpfung: die Datei ist nicht mehr da, lösen lässt sie sich über das Menü des Chips trotzdem. */
.tmdbRecordingMissing {
	color: #c88;
}

.tmdbRecordingChip.addChip {
	background: transparent;
	border-style: dashed;
	cursor: pointer;
	font-size: 0.82rem;
	gap: 0.35rem;
	padding: 0.45rem 0.9rem;
}

.tmdbRecordingChip.addChip:disabled {
	cursor: default;
	opacity: 0.5;
}

/* Die technischen Daten der Aufnahmen (siehe inc/tmdbMeta.html#techPills) - eine Zeile je Aufnahme unterhalb der
   Chips.
   Ein Raster statt einzelner Flex-Zeilen, damit die Pillen aller Fassungen bündig untereinander beginnen: Die
   Bezeichnungen sind unterschiedlich lang ("21:9, o. Nachspann" gegen "16:9, Vollbild"), und je Zeile für sich
   ausgerichtet fingen die Pillen jeder Zeile woanders an. Die erste Spalte wächst mit der längsten Bezeichnung. */
/* Oben ausgerichtet statt mittig: Auf schmalen Bildschirmen bricht die Pillenreihe auf mehrere Zeilen um, und die
   Bezeichnung stünde dann mittig neben dem ganzen Block statt neben ihrer ersten Zeile. Dass sie bei einzeiligen
   Reihen trotzdem exakt auf Pillenhöhe sitzt, besorgt die line-height der Bezeichnung. */
.tmdbTechRows {
	align-items: start;
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 0.35rem 0.6rem;
}

/* Ist keine der Aufnahmen analysiert, bleibt das Raster leer - dann soll es auch keinen Abstand aufspannen. */
.tmdbTechRows:has(.tmdbTechPill) {
	margin-top: 1.1rem;
}

/* Die Zeile selbst ist nur eine Klammer: ihre beiden Kinder sollen unmittelbar im Raster oben liegen, damit sie
   sich an dessen Spalten ausrichten. */
.tmdbTechRow {
	display: contents;
}

/* Nur bei mehreren Fassungen/Teilen vorhanden: sagt, zu welcher Aufnahme die Pillen daneben gehören.
   Die line-height entspricht der Pillenhöhe, damit die Bezeichnung mit der ersten Pillenzeile fluchtet - siehe
   align-items:start am Raster. */
.tmdbTechRowLabel {
	color: #8fa3c0;
	font-size: 0.75rem;
	line-height: var(--control-height-small);
}

.tmdbTechPills {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

/* Die Formensprache der Anwendung statt der alten eckigen Tag-Pille: rund wie jedes andere beschriftete Element
   (--control-radius) und auf der Höhe der kompakten Bedienelemente, damit die Reihe zu den Chips darüber passt.
   Gefüllt wird nur angedeutet - es sind Angaben, keine Schaltflächen, sie sollen die Aufnahme-Chips nicht
   überstrahlen. Die feine Linie stammt aus derselben Familie wie die Kachelrahmen (--line-subtle). */
.tmdbTechPill {
	align-items: center;
	background: rgba(102, 153, 221, 0.09);
	border: 1px solid var(--line-subtle);
	border-radius: var(--control-radius);
	color: #c4d2e6;
	display: inline-flex;
	font-size: 0.8rem;
	gap: 0.35rem;
	height: var(--control-height-small);
	padding: 0 0.7rem;
	white-space: nowrap;
}

/* Die Symbole tragen die Bedeutung ("was für eine Angabe ist das?"), der Text den Wert - deshalb dürfen sie
   etwas kräftiger sein als die Schrift daneben, ohne sie zu übertönen. */
.tmdbTechPill i {
	color: #8fb4e8;
	font-size: 1rem;
}

/* HDR ist die einzige Angabe, die eine Aufnahme wirklich heraushebt - der Rest ist Beschreibung. */
.tmdbTechPill.hdr {
	background: rgba(240, 190, 90, 0.14);
	border-color: rgba(240, 190, 90, 0.45);
	color: #f0d68a;
}

.tmdbTechPill.hdr i {
	color: #f0c860;
}

/* Ton- und Untertitel-Pille klappen weitere Spuren auf und sind damit echte Bedienelemente: Sie bekommen die
   volle Fläche und den kräftigen Rahmen der Bedienelemente, damit man ihnen ansieht, dass sich etwas tut.
   Der Selektor muss ".actions" enthalten, sonst nähme ihnen die allgemeine Regel ".actions button"
   (transparent, randlos) die Fläche wieder weg - dieselbe Begründung wie bei .sortPill.
   Aus demselben Grund steht hier das Innenpolster nochmals: ".actions button" setzt 0.25rem und ist mit seinen
   zwei Bestandteilen spezifischer als ".tmdbTechPill". Ohne diese Zeile fiele die anklickbare Pille schmaler
   aus als ihre Nachbarn, und ihr Symbol stünde nicht mehr unter dem der Zeile darüber. */
.actions .tmdbTechPillBtn {
	background: var(--control-bg);
	/* Vollständig notiert statt nur border-color: ".actions button" setzt "border: none" und ist spezifischer als
	   ".tmdbTechPill" - eine bloße Farbangabe liefe daher ins Leere. Der Rahmen fehlte dann nicht nur optisch, die
	   Pille wäre auch 1px schmaler als ihre Nachbarn und ihr Symbol stünde einen Punkt versetzt. */
	border: 1px solid var(--control-border);
	color: var(--control-text);
	cursor: pointer;
	font-family: inherit;
	padding: 0 0.7rem;
}

.actions .tmdbTechPillBtn:active {
	background: var(--control-bg-hover);
	border-color: var(--control-border-hover);
	color: var(--control-text-hover);
}

/* Ebenfalls gegen ".actions button i" (1.2rem): Anklickbar oder nicht ändert nichts an der Bedeutung des
   Symbols, es soll in beiden Fällen gleich groß sein. */
.actions .tmdbTechPillBtn i {
	font-size: 1rem;
}

/* Der Pfeil steht für "hier ist mehr" und tritt deshalb hinter der Angabe selbst zurück. */
.actions .tmdbTechPillBtn .tmdbTechPillCaret {
	font-size: 0.8rem;
	opacity: 0.7;
}

/* Das Flyout listet reinen Text statt Schaltflächen - die Menü-Regeln von ".actions .moreFlyout button, ... a"
   greifen hier also nicht, Abstände und Größe stehen deshalb hier.
   Die Höhenbegrenzung ist nicht theoretisch: Eine MKV des Bestands führt 27 Untertitelspuren, deren Liste
   nachgemessen 571px hoch wurde und damit unten aus dem Fenster ragte (auf dem Handy entsprechend mehr). Ab dieser
   Grenze wird im Flyout gescrollt, statt dass die letzten Einträge unerreichbar sind. */
.tmdbTechFlyout {
	max-height: min(60vh, 22rem);
	max-width: 20rem;
	overflow-y: auto;
	padding: 0.5em 0.7em;
}

.tmdbTechFlyoutItem {
	font-size: 0.85rem;
	padding: 0.15em 0;
	white-space: nowrap;
}

/* Nur beim Ton: dort steht die Hauptspur bereits in der Pille, ohne Überschrift wirkte die Liste sonst wie die
   vollständige Aufzählung. Bei den Untertiteln steht ohnehin alles darin, da wäre sie nur Ballast. */
.tmdbTechFlyoutTitle {
	color: #8fa3c0;
	font-size: 0.72rem;
	letter-spacing: 0.02em;
	padding-bottom: 0.25em;
	text-transform: uppercase;
}

/* Staffel/Episoden-Detailseiten (Fortsetzung) ------------------------------------------------------ */

.tmdbEpisodeList {
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
	margin-top: 1rem;
}

/* Bewusst kein overflow:hidden hier (analog .tmdbTile, siehe dort) - das würde das .moreFlyout-Dropdown der Karte
   abschneiden, sobald es über den Kartenrand hinausragt. Stattdessen rundet .tmdbEpisodeStillWrap seine Ecken selbst ab. */
.tmdbEpisodeCard {
	align-items: flex-start;
	background: var(--surface);
	border: 1px solid var(--line-subtle);
	border-radius: 8px;
	color: #ddd;
	display: flex;
	/* Der Header ist fixed (siehe "Header") - ohne das läge die per Anker angesprungene Karte (siehe movielist.html)
	   direkt dahinter verdeckt. */
	scroll-margin-top: 4.5rem;
}

.tmdbEpisodeCard:active {
	box-shadow: 0 6px 18px rgba(0,0,0,0.45);
}

/* Per Anker angesprungene Karte (siehe movielist.html) optisch hervorheben: */
.tmdbEpisodeCard:target {
	border-color: #6af;
}

.tmdbEpisodeStillWrap {
	background: var(--page-bg);
	border-radius: 8px 0 0 8px;
	flex: 0 0 18rem;
	height: 10.125rem;
	overflow: hidden;
	position: relative;
	width: 18rem;
}

/* Das Bild füllt die Umhüllung, und der Verweis dazwischen (siehe inc/tmdbEpisodeCard.html) muss die Höhe
   durchreichen - sonst bezöge sich das height:100% des Bildes auf einen in sich zusammengefallenen Kasten: */
.tmdbEpisodeStillLink {
	display: block;
	height: 100%;
}

.tmdbEpisodeStill,
.tmdbEpisodeStillPlaceholder {
	height: 100%;
	width: 100%;
}

.tmdbEpisodeStill {
	display: block;
	object-fit: cover;
}

.tmdbZoomable {
	cursor: zoom-in;
}

.tmdbEpisodeStillPlaceholder {
	align-items: center;
	color: var(--text-faint);
	display: flex;
	font-size: 2rem;
	justify-content: center;
}

/* Folgen-Detailseite: das Bild steht wie das Poster der Filmdetailseite fest links neben den Angaben (deshalb auch
   deren .tmdbMovieDetailHero/.tmdbMovieDetailInfo, siehe .tmdbPersonPhoto), aber im 16:9-Seitenverhältnis des
   Folgenbilds statt im Poster-Format - height:100% aus .tmdbEpisodeStill/-Placeholder griffe hier ins Leere, da
   anders als bei der Kachel keine feste Höhe vorgegeben ist. */
.tmdbEpisodeDetailStill {
	flex: none;
	position: relative;
	width: 20rem;
}

.tmdbEpisodeDetailStill .tmdbEpisodeStill,
.tmdbEpisodeDetailStill .tmdbEpisodeStillPlaceholder {
	aspect-ratio: 16 / 9;
	border-radius: 8px;
	height: auto;
}

.tmdbEpisodeInfo {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 0.4rem;
	min-width: 0;
	padding: 0.6rem 0.8rem;
}

.tmdbEpisodeInfoTop {
	align-items: baseline;
	display: flex;
	gap: 0.5rem;
}

.tmdbEpisodeLabel {
	color: #9ac;
	flex: 0 0 auto;
	font-size: 0.85rem;
	font-weight: bold;
}

/* In der Detail-Überschrift wächst die Nummer mit der übrigen Schrift mit, statt wie in der Folgenkachel klein
   danebenzustehen: */
.tmdbDetailTitle .tmdbEpisodeLabel {
	font-size: inherit;
}

.tmdbEpisodeTitle {
	flex: 1;
	font-weight: bold;
	overflow-wrap: anywhere;
}

.tmdbEpisodeInfoTop .tmdbToggleWatchedBtn,
.tmdbEpisodeInfoTop .tmdbEpisodeDetailsBtn,
.tmdbEpisodeInfoTop .actions {
	flex: 0 0 auto;
	text-decoration: none;
}

/* Nur das erste der drei schiebt die Gruppe nach rechts - :first-of-type griffe hier nicht, die drei sind
   button, a und span. */
.tmdbEpisodeInfoTop .tmdbToggleWatchedBtn {
	margin-left: auto;
}

.tmdbEpisodeInfoTop .tmdbToggleWatchedBtn + .tmdbEpisodeDetailsBtn,
.tmdbEpisodeInfoTop .tmdbEpisodeDetailsBtn:first-child {
	margin-left: 0;
}

.tmdbEpisodeInfoTop .tmdbEpisodeDetailsBtn:not(.tmdbToggleWatchedBtn + *) {
	margin-left: auto;
}

/* Serienweite Folgensuche (siehe tmdbEpisodeSearch.js) ------------------------------------------
 *
 * Eigene, kompaktere Kachel statt .tmdbEpisodeCard: hier zählen viele Treffer auf einen Blick, nicht die
 * Detailangaben einer einzelnen Folge. Der Serienname fehlt bewusst - gesucht wird immer innerhalb einer Serie.
 */
.tmdbEpisodeSearchRow {
	align-items: center;
	display: flex;
	gap: 0.5rem;
	margin-bottom: 0.75rem;
}

.tmdbEpisodeSearchRow .dialogInput {
	flex: 1;
	min-width: 0;
}

.tmdbEpisodeSearchResults {
	align-content: start;
	display: grid;
	gap: 0.6rem;
	grid-auto-rows: max-content;
	grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
	min-height: 0;
	overflow-y: auto;
}

.tmdbEpisodeSearchHit {
	background: var(--surface);
	border: 1px solid var(--line-subtle);
	border-radius: 8px;
	color: #ddd;
	display: flex;
	overflow: hidden;
	text-decoration: none;
}

.tmdbEpisodeSearchHit:active {
	border-color: #9ac;
}

.tmdbEpisodeSearchStillWrap {
	background: var(--page-bg);
	flex: 0 0 7.5rem;
	height: 4.22rem;
	position: relative;
	width: 7.5rem;
}

.tmdbEpisodeSearchStill {
	display: block;
	height: 100%;
	object-fit: cover;
	width: 100%;
}

.tmdbEpisodeSearchInfo {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 0.25rem;
	min-width: 0;
	padding: 0.4rem 0.6rem;
}

.tmdbEpisodeSearchTitle {
	display: flex;
	font-weight: bold;
	gap: 0.4rem;
}

.tmdbEpisodeSearchName {
	min-width: 0;
	overflow-wrap: anywhere;
}

.tmdbEpisodeSearchSnippet {
	color: #aaa;
	font-size: 0.8rem;
	margin: 0;
	overflow-wrap: anywhere;
}

/* Der Treffer wird über <strong> hervorgehoben (siehe highlight() in tmdbEpisodeSearch.js) - hier zusätzlich
   farblich, damit er im gedämpften Ausschnittstext auch wirklich ins Auge springt: */
.tmdbEpisodeSearchSnippet strong,
.tmdbEpisodeSearchTitle strong {
	color: #fff;
}

.tmdbEpisodeSearchTags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem;
}

/* Tag-Pille der verknüpften Aufnahmen - gemeinsam genutzt von der Folgenkachel, der Filmdetailseite (beide über
   inc/tmdbMeta.html#tagPills) und den Trefferkacheln der Folgensuche. */
/* Beim Durchscrollen der Folgenliste sollen die Tags sofort ins Auge fallen, dürfen aber nicht wie eine Schaltfläche
   aussehen. Deshalb bewusst anders als die Pillen darunter (siehe .tmdbEpisodeActions .playMovie): eckig statt rund,
   hell gefüllt statt umrandet, und in neutralem Grau statt im Buttonblau. Das Tag-Symbol macht vollends klar, dass
   hier eine Angabe steht und nichts zu drücken ist. */
.tmdbTagPill {
	align-items: center;
	background: #39435c;
	border-radius: 3px;
	color: #d3dcea;
	display: inline-flex;
	/* Fett und eine Spur größer als die Nachbarangaben: die Tags sollen sich beim Durchscrollen der Folgenliste
	   sofort erfassen lassen. */
	font-size: 0.78rem;
	font-weight: 600;
	gap: 0.2rem;
	/* Oben/unten bewusst mehr Luft als der Text bräuchte - die Pille soll als Fläche wirken, nicht wie eng
	   umschlossene Schrift. */
	padding: 0.15rem 0.4rem;
	white-space: nowrap;
}

/* Nur in der Suche: hebt das Tag hervor, wegen dem die Folge im Ergebnis steht - genau die Umkehrung der
   Grundfarben. */
.tmdbTagPill.matched {
	background: #d3dcea;
	color: #39435c;
}

.tmdbEpisodeInfoTop .tmdbToggleWatchedBtn:active {
	color: #fff;
}

.tmdbEpisodeMeta {
	align-items: center;
	color: #aaa;
	display: flex;
	flex-wrap: wrap;
	font-size: 0.78rem;
	gap: 0.6rem;
}

.tmdbEpisodeOverview {
	color: #ccc;
	font-size: 0.82rem;
	line-height: 1.4;
	margin: 0;
}

.tmdbEpisodeActions {
	align-items: center;
	display: flex;
	/* Lieber die Zeile umbrechen als die Beschriftung in der Pille: Auf dem Handy schrumpften die Stream-Knöpfe
	   sonst so weit, dass "Streamen (ext. Player)" zweizeilig in der Pille stand. */
	flex-wrap: wrap;
	gap: 0.8rem;
	margin-top: auto;
}

.tmdbEpisodeActions .playMovie {
	align-items: center;
	background: transparent;
	border: none;
	color: #9ac;
	cursor: pointer;
	display: inline-flex;
	font-size: 0.78rem;
	gap: 0.25rem;
	padding: 0;
}

.tmdbEpisodeActions .playMovie:active {
	color: #fff;
}

/* Auf den Detailseiten stehen die technischen Daten frei unter den Chips und brauchen deshalb reichlich Luft
   (1.1rem). In der Kachel liegen sie im Spaltenfluss von .tmdbEpisodeInfo, der bereits 0.4rem Abstand mitbringt -
   der volle Wert ergäbe zusammen 1.5rem und risse die Kachel unnötig auseinander. */
.tmdbEpisodeCard .tmdbTechRows:has(.tmdbTechPill) {
	margin-top: 0.25rem;
}

/* Handy hochkant: Standbild und Text nebeneinander lohnen sich nicht mehr - das 16:9-Bild ist dann nur noch
   halb so hoch wie die Karte (darunter bliebe toter Leerraum) und lässt der Beschreibung weniger als die halbe
   Breite. Stattdessen gestapelt: Bild in voller Breite oben, Text darunter. */
@media (max-width: 640px) {
	.tmdbEpisodeCard {
		flex-direction: column;
	}

	.tmdbEpisodeStillWrap {
		aspect-ratio: 16 / 9;
		border-radius: 8px 8px 0 0;
		flex: 0 0 auto;
		height: auto;
		width: 100%;
	}
}

.tmdbFutureHint {
	font-size: 0.8rem;
	margin-left: 0.5rem;
	color: #aaa;
}

.tmdbUnmatchedTitle {
	margin-top: 2rem;
}

.tmdbUnmatchedHint {
	color: #aaa;
}

.tmdbUnmatchedList {
	color: #ccc;
}

/* Ein Serien-Abschnitt auf der Seite der nicht aufgehenden Aufnahmen (siehe tmdbunmatched.html). In der
   Gesamtansicht stehen mehrere davon untereinander, deshalb eine sichtbare Trennung. */
.tmdbUnmatchedSeries + .tmdbUnmatchedSeries {
	border-top: 1px solid var(--line-subtle);
	margin-top: 2rem;
}

.tmdbUnmatchedSeriesTitle {
	margin-bottom: 0.3rem;
}

.tmdbUnmatchedActions {
	margin-top: 1rem;
}

@media (max-width: 640px) {
	.tmdbGrid {
		grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
	}

	/* Mit den schmaleren Kacheln muss auch das Fragezeichen kleiner werden, sonst läuft es seitlich heraus. */
	.tmdbTile.tmdbTileMuted .tmdbPosterPlaceholder {
		font-size: 6.5rem;
	}

	/* In einer nur ~8rem breiten Kachel reicht der Platz für "TMDB" und "Trailer" im Klartext nicht mehr - hier
	   bleiben die Icons allein stehen, ihre Bedeutung nennt weiterhin der title-Tooltip. Nur in den Kacheln: die
	   Pills der Detailseiten haben die ganze Seitenbreite und behalten ihre Beschriftung. */
	.tmdbTileLinks .tmdbExternalLink span {
		display: none;
	}

	/* Ausnahme Portal: Dort steht in der Zeile nur noch der Trailer-Link, der TMDB-Link daneben ist ausgeblendet
	   (siehe body.portalMode .tmdbTileLinks). Der Platz, den das freimacht, ist genau der, der hier fehlte - und ein
	   einzelnes Zeichen ohne Beschriftung ist für jemanden, der die Mediathek nur zum Ansehen benutzt, schlechter zu
	   deuten als für einen Administrator. Gezielt der YouTube-Link, nicht .tmdbExternalLink allgemein: Sonst bekäme
	   ein künftiger Link dort seine Beschriftung zurück, ohne dass jemand darüber nachgedacht hat. */
	body.portalMode .tmdbTileLinks .tmdbYoutubeLink span {
		display: inline;
	}
}

/* Verknüpfungs-Badges/-Buttons auf MovieDirsPage/MovieListPage --------------------------------- */

.actions .actionFlyout a.tmdbGotoSeries,
.actions .actionFlyout a.tmdbGotoMovie {
	align-items: center;
	color: #6af;
	display: inline-flex;
	padding: 0.25rem 0.25rem;
}

.actions.actionsSmall .actionFlyout a.tmdbGotoSeries {
	padding: 0.1rem 0.1rem;
}

.actions .actionFlyout a.tmdbGotoSeries i,
.actions .actionFlyout a.tmdbGotoMovie i {
	font-size: 1.2rem;
}

/* Auf schmalen Bildschirmen ist das .actionFlyout ein senkrechtes Menü (siehe dort), in dem diese beiden Links
   ganz normale Einträge sind: Innenabstand und Beschriftungsfarbe wie bei den Buttons daneben statt der kompakten
   Badge-Darstellung aus der Icon-Reihe. Der Block steht hier unten und nicht oben in der Media Query, weil die drei
   Regeln darüber sonst gleichauf lägen und als spätere im Dokument gewönnen.
   Die Maße müssen dieselben rem-Werte sein wie bei den Menüeinträgen oben - warum nicht em, steht dort. */
@media (max-width: 1024px) {

	.actions .actionFlyout > a.tmdbGotoSeries,
	.actions .actionFlyout > a.tmdbGotoMovie,
	.actions.actionsSmall .actionFlyout > a.tmdbGotoSeries {
		color: white;
		padding: 0.35rem 0.625rem;
	}

	/* Das Icon bleibt blau, auch wenn die Beschriftung weiß ist wie überall im Menü: Es ist das einzige Zeichen
	   dafür, dass hier bereits eine TMDB-Verknüpfung besteht (der Eintrag heißt sonst nur "Zum TMDB-Film"). Auf
	   breiten Bildschirmen sagt das dasselbe blaue Symbol in der Icon-Reihe, siehe die Regel weiter oben. */
	.actions .actionFlyout > a.tmdbGotoSeries i,
	.actions .actionFlyout > a.tmdbGotoMovie i {
		color: #6af;
	}
}

/* Bewertung und externe Links (TMDB/YouTube) ---------------------------------------------------- */

.tmdbRating {
	color: #fc6;
	margin-left: 0.4rem;
	white-space: nowrap;
}

/* Als Flyout-Auslöser auf den Detailseiten ist die Bewertung eine Schaltfläche (siehe das Makro ratingFlyout). Der
   Reset in ".actions button" ist spezifischer als ".tmdbRating" und färbte sie sonst weiß; Schriftart und Innenabstand
   kämen ebenfalls von dort. Gleiches Muster wie bei ".actions .tmdbTechPillBtn". */
.actions .tmdbRating {
	color: #fc6;
	cursor: pointer;
	font-family: inherit;
	font-size: inherit;
	padding: 0;
}

/* Gegen ".actions button i" (1.2rem): Ob anklickbar oder nicht ändert nichts an der Größe des Sterns. */
.actions .tmdbRating i {
	font-size: 1rem;
}

/* Nimmt die Regel eine Zeile darüber vom Pfeil wieder zurück, damit er so klein bleibt wie an den übrigen Pillen
   (siehe .tmdbFlyoutCaret). */
.actions .tmdbRating .tmdbFlyoutCaret {
	font-size: 0.7em;
}

/* Die Zeilen des Bewertungs-Flyouts stehen in drei Spalten (Quelle, Wert, Einordnung), damit Sterne und Zahlen
   untereinander stehen: "IMDb" ist schmaler als "TMDB", nebeneinandergeschrieben liefen die Werte sonst versetzt.
   max-content nimmt die Breite der längsten Quelle, sodass eine weitere Zeile (etwa Trakt) ohne Anpassung mitgeht.

   Der lange Selektor ist nötig: ".actions .moreFlyout.open" setzt display:flex und gap und ist spezifischer als eine
   einzelne Klasse - die Zellen stünden sonst als schmale Spalte untereinander. */
.actions .moreFlyout.tmdbRatingFlyout.open {
	align-items: baseline;
	column-gap: 0.45em;
	display: grid;
	grid-template-columns: max-content max-content max-content;
	row-gap: 0.15em;
}

/* Die Überschrift ist keine Zeile des Rasters, sondern steht über allen drei Spalten. */
.tmdbRatingFlyout .tmdbTechFlyoutTitle {
	grid-column: 1 / -1;
}

/* Wie .tmdbTechFlyoutItem, dessen Platz die drei Zellen einnehmen - bewusst je Klasse und nicht über den Nachfahren
   "span", da das auch die kleiner gesetzte Überschrift träfe. */
.tmdbRatingFlyoutSource,
.tmdbRatingFlyoutValue,
.tmdbRatingFlyoutExtra {
	font-size: 0.85rem;
	white-space: nowrap;
}

/* Stern und Wert tragen dieselbe Farbe wie die Pille darüber - beides zusammen oder gar nicht, ein andersfarbiger
   Stern neben einem Wert in Textfarbe sähe nach Versehen aus. Quelle und Einordnung bleiben in der Textfarbe und
   treten damit hinter die Zahl zurück, auf die es ankommt. */
.tmdbRatingFlyoutValue {
	color: #fc6;
}

.tmdbRatingFlyoutValue i {
	margin-right: 0.15rem;
}

/* Die Zahl der Stimmen hinter der Bewertung: in der gedämpften Textfarbe der übrigen Nebenangaben und kleiner
   gesetzt, denn sie ordnet die Bewertung nur ein und soll ihr nicht die Aufmerksamkeit nehmen. */
.tmdbVoteCount {
	color: var(--text-muted);
	font-size: 0.85em;
	margin-left: 0.25rem;
}

/* Kompakte Kennzahl mit Icon in den Meta-Zeilen der Detailseiten (siehe inc/tmdbMeta.html#stat). Die Farben
   entsprechen den Kennzeichen auf den Postern, damit Icon und Badge dieselbe Bedeutung tragen. */
.tmdbStat {
	margin-left: 0.6rem;
	white-space: nowrap;
}

.tmdbStat i {
	margin-right: 0.2rem;
}

/* Dieselben Farben stehen den Kopfzeilen der Übersichtsseiten zur Verfügung, wo die Kennzahl ausgeschrieben und
   nicht als .tmdbStat aufgebaut ist (siehe tmdbmovies.html/tmdbseries.html): */
.tmdbStat.collected i,
.tmdbIconCollected {
	color: #6af;
}

.tmdbStat.watched i,
.tmdbIconWatched {
	color: #6c6;
}

/* Lila wie das Filmreihen-Kennzeichen auf dem Poster (.tmdbBadge.collectionMark) - das Stapel-Icon steht überall
   im Bereich für "Filmreihe/Sammlung": */
.tmdbStat.inCollection i,
.tmdbIconCollection {
	color: #cae;
}

/* Überschrift der Detailseiten mit den Blätter-Pfeilen dahinter (Staffel bzw. Film einer Reihe): */
.tmdbDetailTitle {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}

.tmdbTitleNav {
	display: inline-flex;
	gap: 0.2rem;
}

.tmdbTitleNav a,
.tmdbTitleNav .disabled {
	align-items: center;
	background: #1b2b52;
	border: 1px solid #4a70b0;
	border-radius: 50%;
	color: #cfe0f5;
	display: inline-flex;
	font-size: 1.1rem;
	height: 2rem;
	justify-content: center;
	width: 2rem;
}

.tmdbTitleNav a:active {
	background: #2a4383;
	border-color: #7aa0e0;
	color: #fff;
}

/* Am Anfang bzw. Ende bleibt der Pfeil stehen statt zu verschwinden - sonst springt der jeweils andere an seine
   Stelle und man klickt beim Durchblättern daneben: */
.tmdbTitleNav .disabled {
	border-color: #2a3a5a;
	color: var(--text-faint);
}

.tmdbRating i {
	margin-right: 0.15rem;
}

/* TMDB-Link, Trailer-Link und "..."-Menü teilen sich hier gut 8rem - eine Kachel ist nur ~9,5rem breit, und wie
   breit sie wirklich wird, bestimmt das Grid je nach Fensterbreite (auto-fill mit 1fr, siehe .tmdbGrid). Mit zu
   großen Abständen wurde das Menü aus der Kachel herausgeschoben - in der rechten Spalte aus dem Fenster heraus,
   was die Seite waagerecht scrollbar machte.

   Den sichtbaren Abstand erzeugt deshalb space-between aus dem freien Rest - das hält die Lücken untereinander
   gleich, statt (wie zuvor per margin-left:auto am Menü) den gesamten Rest in die letzte Lücke zu legen und dadurch
   ungleichmäßig zu wirken. Der column-gap ist dabei nur die Untergrenze, ab der umbrochen wird, und deshalb 0: schon
   ein Millimeter Mindestabstand kostet in der engsten Kachel genau die Zeile.

   flex-wrap bleibt als Sicherheitsnetz für den Fall, dass es doch einmal nicht reicht (größere Schrift). */
.tmdbTileLinks {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 0;
	justify-content: space-between;
	margin: 0 0.5rem 0.5rem 0.5rem;
}

/* margin-left:auto würde den gesamten freien Platz an sich ziehen und space-between damit aushebeln: */
.tmdbTileLinks .tmdbTileMoreActions,
.tmdbTileLinks .tmdbAddPartBtn {
	margin-left: 0;
}

/* Der knappe gap zwischen Icon und Beschriftung ist Teil der Platzrechnung der Kachel-Linkzeile (siehe
   .tmdbTileLinks); die Pills der Detailseiten setzen sich davon bewusst ab und bringen ihren eigenen mit. */
.tmdbExternalLink {
	align-items: center;
	color: #9ac;
	display: inline-flex;
	font-size: 0.78rem;
	gap: 0.125rem;
	text-decoration: none;
}

.tmdbExternalLink:active {
	color: #fff;
}

.tmdbYoutubeLink {
	color: #e55;
}

.tmdbYoutubeLink:active {
	color: #f88;
}

/* Die Pille für die eigenen Videoclips einer Serie ("... 0x00 - Trailer"). Immer ein <button>, da sie die Aufnahme
   auf der Dreambox startet statt einem Link zu folgen - deshalb der Reset auf die Optik der <a>-Pillen daneben.
   Farblich bewusst wie die übrigen Bedienelemente und nicht wie die rote YouTube-Pille: sie führt nicht nach außen. */
button.tmdbExternalLink {
	background: transparent;
	border: none;
	cursor: pointer;
	font-family: inherit;
	padding: 0;
}

/* Etwas mehr Luft als bei den Nachbarpillen: das schmale Play-Dreieck rückt sonst an die Beschriftung heran,
   während die breiten, quadratischen Icons daneben (YouTube-Logo, Pfeil im Kasten) von selbst Abstand halten. */
.tmdbLocalVideoLink {
	gap: 0.25rem;
}

/* Die Meta-Zeile der Detailseiten (Angaben, Bewertung, am Ende die Pills). Bewusst Flexbox statt Textfluss: auf
   schmalen Bildschirmen rutschen die Pills in eine eigene Zeile, und im Textfluss sähe das an beiden Enden falsch
   aus - ein Umbruch erzeugt dort keinen Abstand nach oben, während das margin-left der Pills als Einzug von links
   stehen bliebe. Als Flex-Zeile übernimmt das der row-gap, und der Abstand zwischen den Angaben kommt aus dem
   column-gap, der beim Umbruch von selbst verschwindet. */
.tmdbMetaLine {
	align-items: center;
	column-gap: 0.6rem;
	display: flex;
	flex-wrap: wrap;
	row-gap: 0.5rem;
}

/* In der Flex-Zeile trennt der column-gap; die eigenen Abstände der Bausteine kämen sonst obendrauf und wirkten
   nach einem Umbruch wieder als Einzug: */
.tmdbMetaLine .tmdbStat,
.tmdbMetaLine .tmdbRating,
.tmdbMetaLine .tmdbDetailLinks {
	margin-left: 0;
}

/* Der Originaltitel direkt unter der Überschrift: kleiner und grauer als diese, damit er sie ergänzt statt mit ihr
   zu konkurrieren. Der negative obere Abstand holt ihn dicht an den Titel heran - er gehört zu ihm, während die
   Tagline darunter eine eigene Aussage ist. */
.tmdbOriginalTitle {
	color: var(--text-muted);
	font-size: 0.85rem;
	margin: -0.6rem 0 0.5rem 0;
}

/* Gleiches Element im Detail-Popup-Kopf (siehe base.html): dort sitzt der Titel nicht unter einer großen Überschrift,
   sondern in der schmalen Dialog-Kopfzeile - daher kleiner und ohne den negativen Abstand der Detailseiten-Variante. */
.tmdbDetailPopupTitleBlock .tmdbOriginalTitle {
	font-size: 0.75rem;
	margin: 0.1rem 0 0 0;
}

/* Kurzer Werbespruch der Detailseiten (Film/Serie), zwischen Titel und Meta-Zeile. Bewusst nicht var(--text-faint):
   das ist die Farbe für abgeschaltete Bedienelemente und für einen kursiven Satz auf dem dunklen Hintergrund zu
   schwach - hier soll er gedämpft, aber lesbar sein. */
.tmdbTagline {
	color: #9ab;
	font-style: italic;
	margin: 0 0 0.5rem 0;
}

/* Genres/Produktionsländer, zwischen Meta-Zeile und Inhaltsangabe - dieselbe gedämpfte Farbe wie .tmdbOverview,
   aber kleiner, da reine Zusatzinfo statt Fließtext. Die Serienzeile (Status, nächste Folge, Sender, Erfinder)
   steht direkt darunter und sieht bewusst genauso aus - beides sind Angaben zum Titel, keine Bedienelemente. */
.tmdbGenreLine,
.tmdbSeriesLine {
	color: #ccc;
	font-size: 0.85rem;
	margin: 0 0 0.6rem 0;
}

/* Zwischen beiden Zeilen soll kein doppelter Abstand stehen: */
.tmdbGenreLine + .tmdbSeriesLine {
	margin-top: -0.35rem;
}

/* Videos ---------------------------------------------------------------------------------------- */

/* YouTube-Titel werden beliebig lang ("Michael Emerson Joins Elsbeth ("The Good Wife" / ...) CBS Trailer"). Ohne
   Begrenzung wüchse das Flyout mit ihnen und schöbe sich - da es am Auslöser rechts ausgerichtet ist - über die
   Navigationsleiste hinaus: */
.tmdbVideoFlyout {
	max-width: 22rem;
}

/* Im Flyout der Video-Pillen steht die Typ- bzw. Bezeichnungszeile über der Beschreibung; ohne diese Ausrichtung
   säße das Icon neben der zweizeiligen Beschriftung mittig statt an der ersten Zeile. Gilt für beide Pillen: die
   YouTube-Videos sind <a>, die eigenen Aufnahmen <button> (sie starten auf der Dreambox). */
.tmdbVideoFlyout a,
.tmdbVideoFlyout button {
	align-items: flex-start;
}

/* Das Icon darf hier größer ausfallen als in den einzeiligen Menüs: die Beschriftung daneben ist zweizeilig,
   und ein Icon in Standardgröße wirkte daneben verloren. */
.tmdbVideoFlyout a i,
.tmdbVideoFlyout button i {
	font-size: 1.7rem;
}

/* min-width: 0 erlaubt dem Textblock, schmaler als sein Inhalt zu werden - ohne das greift das ellipsis darunter
   nicht, weil ein Flex-Kind standardmäßig nicht unter seine Inhaltsbreite schrumpft: */
.tmdbVideoFlyoutText {
	display: flex;
	flex-direction: column;
	line-height: 1.3;
	min-width: 0;
}

/* Der Typ ist die Gruppierung und trägt deshalb das Gewicht, der Videoname steht als Erläuterung darunter: */
.tmdbVideoFlyout .tmdbVideoType {
	font-weight: bold;
}

/* Sprache und Auflösung hinter dem Typ - gedämpft und ohne dessen Fettung, sie sind nur Beiwerk zur Typangabe: */
.tmdbVideoDetails {
	color: var(--text-muted);
	font-size: 0.8rem;
	font-weight: normal;
	margin-left: 0.3rem;
}

/* Kennzeichnet eine Pille als Flyout-Auslöser (siehe inc/tmdbMeta.html#flyoutCaret). Kleiner als die Beschriftung
   und gedämpft: es ist ein Hinweis auf das Verhalten, kein eigener Inhalt. */
.tmdbFlyoutCaret {
	font-size: 0.7em;
	margin-left: 0.1rem;
	opacity: 0.7;
}

.tmdbVideoFlyout .tmdbVideoName {
	color: var(--text-muted);
	font-size: 0.8rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Der eigene Videobereich der Filmdetailseite (siehe inc/tmdbMeta.html#videoSection). */
.tmdbVideoSection {
	margin-top: 1.5rem;
}

.tmdbVideoSection h3 {
	margin: 0 0 0.6rem 0;
}

/* In jeder Breite eine quer wischbare Reihe, nicht nur am Handy: Zu einem Film können zwei Dutzend Videos gehören
   ("Glass": 24). Umbrechend füllten die allein mehrere Bildschirmhöhen, und was darunter steht - Regie, verknüpfte
   Inhalte, Vorschläge - wäre nur noch über langes Scrollen erreichbar. Eine Zeile hoch bleibt der Bereich das, was
   er ist: ein Angebot am Rand.
   Die angeschnittene nächste Karte am rechten Rand zeigt an, dass es weitergeht. */
.tmdbVideoRow {
	display: flex;
	flex-wrap: nowrap;
	gap: 0.8rem;
	overflow-x: auto;
	padding-bottom: 0.5rem;
	scroll-snap-type: x proximity;
}

.tmdbVideoCard {
	scroll-snap-align: start;
}

.tmdbVideoCard {
	color: inherit;
	flex: none;
	text-decoration: none;
	width: 15rem;
}

/* Eine eigene Aufnahme ist ein <button> (sie startet auf der Dreambox), die YouTube-Videos daneben sind <a> - beide
   sollen gleich aussehen. align-self verhindert dabei, dass die Reihe den Button auf die Höhe der höchsten Karte
   streckt: ein Button zentriert seinen Inhalt vertikal, wodurch Vorschaufläche und Beschriftung tiefer säßen als
   nebenan. */
button.tmdbVideoCard {
	align-self: start;
	background: transparent;
	border: none;
	cursor: pointer;
	font-family: inherit;
	font-size: inherit;
	padding: 0;
	text-align: left;
}


/* Bezugspunkt für das Play-Symbol, das absolut darüber liegt: */
.tmdbVideoThumb {
	background: #0d1424;
	border-radius: 8px;
	display: block;
	overflow: hidden;
	position: relative;
}

/* Von einer eigenen Aufnahme gibt es kein Vorschaubild - die Fläche bleibt leer und trägt nur das Play-Symbol, das
   auch auf den YouTube-Karten daneben liegt. Der 16:9-Ausschnitt kommt hier von der Kachel selbst statt vom Bild.
   Sie braucht dabei einen eigenen, helleren Hintergrund als .tmdbVideoThumb: dessen #0d1424 ist der Seitenfarbe so
   nah, dass die leere Fläche unsichtbar wäre und das Play-Symbol frei zu schweben schiene. */
.tmdbVideoThumbLocal {
	aspect-ratio: 16 / 9;
	background: var(--surface);
	width: 100%;
}

/* 16:9 wie das mqdefault-Vorschaubild - fest gesetzt, damit die Reihe beim Nachladen der Bilder nicht springt: */
.tmdbVideoThumb img {
	aspect-ratio: 16 / 9;
	display: block;
	object-fit: cover;
	width: 100%;
}

.tmdbVideoPlay {
	align-items: center;
	background: rgba(0, 0, 0, 0.55);
	border-radius: 50%;
	color: #fff;
	display: flex;
	font-size: 1.4rem;
	height: 3rem;
	justify-content: center;
	left: 50%;
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 3rem;
}

.tmdbVideoCard:active .tmdbVideoPlay {
	background: #e55;
}

/* Auf einer eigenen Aufnahme ist das Play-Symbol das einzige Element der leeren Fläche - der abgedunkelte Kreis der
   YouTube-Karten ergäbe hier keinen Sinn, er hebt sich dort ja von einem Bild ab. Stattdessen die Optik der runden
   Icon-Schaltflächen des Bereichs (siehe .tmdbIconBtn): Das sagt zugleich, dass hier etwas im Haus startet und nicht
   im Browser aufgeht. */
.tmdbVideoThumbLocal .tmdbVideoPlay {
	background: #1b2b52;
	border: 1px solid #4a70b0;
	color: #cfe0f5;
}

.tmdbVideoCard:active .tmdbVideoThumbLocal .tmdbVideoPlay {
	background: #2a4383;
	border-color: #7aa0e0;
	color: #fff;
}

/* Auf den YouTube-Karten steht das Logo an der Stelle des Abspiel-Dreiecks (siehe inc/tmdbMeta.html#videoSection).
   Ohne den dunklen Kreis der Abspiel-Schaltfläche: das Logo hat mit seiner eigenen Fläche schon eine Form, im Kreis
   säße Rund in Rund. Bewusst nicht in der Markenfarbe, sondern hell und halbdurchsichtig wie ein Wasserzeichen -
   es unterscheidet die Karte von einer eigenen Aufnahme, soll aber neben dem Vorschaubild nicht um Aufmerksamkeit
   ringen. Der Schatten hält es auch auf hellen Bildern lesbar. */
.tmdbVideoPlayYoutube {
	background: none;
	color: rgba(255, 255, 255, 0.8);
	font-size: 3rem;
	height: auto;
	text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
	width: auto;
}

.tmdbVideoCard:active .tmdbVideoPlayYoutube {
	background: none;
	color: #fff;
}

.tmdbVideoCard .tmdbVideoType {
	display: block;
	font-weight: bold;
	margin-top: 0.4rem;
}

/* Lange Videonamen auf zwei Zeilen begrenzen, damit die Kacheln der Reihe gleich hoch bleiben: */
.tmdbVideoCard .tmdbVideoName {
	color: var(--text-muted);
	display: -webkit-box;
	font-size: 0.8rem;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

/* Regie & Besetzung ----------------------------------------------------------------------------- */

/* Aufbau und Verhalten wie beim Videobereich darüber (siehe .tmdbVideoSection): am Desktop umbrechend, auf dem
   Handy eine quer wischbare Reihe. Die Karten sind allerdings halb so breit - ein Profilbild steht hochkant, wo
   ein Video-Vorschaubild quer liegt, und so passen doppelt so viele Personen in eine Zeile. */
.tmdbCreditSection {
	margin-top: 1.5rem;
}

.tmdbCreditSection h3 {
	margin: 0 0 0.6rem 0;
}

.tmdbCreditRow {
	display: flex;
	flex-wrap: wrap;
	gap: 0.8rem;
}

.tmdbCreditCard {
	color: inherit;
	flex: none;
	text-decoration: none;
	width: 7.5rem;
}

.tmdbCreditPhoto {
	background: #0d1424;
	border-radius: 8px;
	display: block;
	overflow: hidden;
}

/* 2:3 wie ein Poster - fest gesetzt, damit die Reihe beim Nachladen der Bilder nicht springt und Karten mit und
   ohne Foto gleich hoch bleiben: */
.tmdbCreditPhoto img,
.tmdbCreditPlaceholder {
	aspect-ratio: 2 / 3;
	display: block;
	object-fit: cover;
	width: 100%;
}

.tmdbCreditPlaceholder {
	align-items: center;
	color: var(--text-faint);
	display: flex;
	font-size: 2.5rem;
	justify-content: center;
}

.tmdbCreditName {
	display: block;
	font-weight: bold;
	margin-top: 0.4rem;
}

/* Lange Rollennamen auf zwei Zeilen begrenzen, damit die Karten gleich hoch bleiben (wie bei den Videonamen): */
.tmdbCreditRole {
	color: var(--text-muted);
	display: -webkit-box;
	font-size: 0.8rem;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

@media (max-width: 640px) {
	.tmdbCreditRow {
		flex-wrap: nowrap;
		overflow-x: auto;
		padding-bottom: 0.5rem;
		scroll-snap-type: x proximity;
	}

	.tmdbCreditCard {
		scroll-snap-align: start;
	}
}

/* Titelkarten (ähnliche Titel, Filmografie) --------------------------------------------------------------------------- */

/* Aufbau wie die Video- und Besetzungs-Reihe darüber (siehe .tmdbVideoRow): am Desktop umbrechend, auf dem Handy
   quer wischbar. Die Karten sind so breit wie die der Besetzung - beide zeigen ein Bild im Hochformat. */
.tmdbTitleCardSection {
	margin-top: 1.5rem;
}

.tmdbTitleCardSection h3 {
	align-items: center;
	display: flex;
	gap: 0.5rem;
	margin: 0 0 0.6rem 0;
}

/* Die verlinkte Überschrift soll wie eine Überschrift aussehen, nicht wie ein Link - der Weg zur vollen Ansicht
   ist ein Angebot, keine Ansage. Sie erbt deshalb Farbe und Schrift und zeigt sich erst beim Überfahren. */
.tmdbTitleCardHeadingLink {
	align-items: center;
	color: inherit;
	display: flex;
	gap: 0.5rem;
	text-decoration: none;
}

.tmdbTitleCardHeadingLink:hover {
	text-decoration: underline;
}

/* Sagt nur "Filme" oder "Serien" und steht damit deutlich unter dem Namen der Reihe davor: kleiner und
   zurückgenommen, wie die Meta-Angaben unter den Karten (siehe .tmdbTitleCardMeta). */
.tmdbTitleCardGroupIcon {
	color: var(--text-muted);
	font-size: 0.8em;
}

.tmdbTitleCardRow {
	display: flex;
	flex-wrap: wrap;
	gap: 0.8rem;
}

/* Die nicht übernommenen Titel sind Schaltflächen (sie öffnen ein Popup), die übernommenen Links - beide sollen
   gleich aussehen, deshalb werden hier die Vorgaben für Schaltflächen zurückgenommen: */
.tmdbTitleCard {
	background: none;
	border: none;
	color: inherit;
	cursor: pointer;
	display: block;
	flex: none;
	font: inherit;
	padding: 0;
	text-align: left;
	text-decoration: none;
	width: 7.5rem;
}

/* Bezugspunkt für die Kennzeichen, die absolut in den Ecken sitzen (siehe .tmdbBadges/.tmdbBadgesLeft): */
.tmdbTitleCardPoster {
	background: #0d1424;
	border-radius: 8px;
	display: block;
	overflow: hidden;
	position: relative;
}

.tmdbTitleCardPoster img {
	aspect-ratio: 2 / 3;
	display: block;
	object-fit: cover;
	width: 100%;
}

/* Nur die Bildmaße übernehmen, nicht display:block wie beim <img> darüber: Das Platzhaltersymbol zentriert sich
   per display:flex (siehe .tmdbPosterPlaceholder) - mit block stand es zuvor oben links statt mittig. */
.tmdbTitleCardPoster .tmdbPosterPlaceholder {
	aspect-ratio: 2 / 3;
	width: 100%;
}

/* Lange Titel auf zwei Zeilen begrenzen, damit die Karten gleich hoch bleiben (wie bei den Videonamen).

   Dieselbe Schriftgröße wie auf den großen Kacheln der Übersichten (siehe .tmdbTileTitle): Wenn sie dort reicht,
   reicht sie hier erst recht - diese Karten sind schmaler, und der zuvor größere Titel verbrauchte gerade auf
   ihnen den knappen Platz. Bewusst nicht auf .tmdbCreditName übertragen: Die Karten von "Regie & Besetzung"
   bleiben, wie sie sind. */
.tmdbTitleCardName {
	display: -webkit-box;
	font-size: 0.85rem;
	font-weight: bold;
	margin-top: 0.4rem;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

.tmdbTitleCardMeta {
	color: var(--text-muted);
	display: block;
	font-size: 0.8rem;
}

/* Die Rolle in diesem Titel - nur auf der Personenseite vorhanden, dort der Grund, warum er überhaupt erscheint.
   Auf zwei Zeilen begrenzt, damit die Karten gleich hoch bleiben.

   Bewusst nicht var(--text-faint): Das ist die Farbe abgeschalteter Bedienelemente und für Text schon auf einer
   normalen Karte zu schwach - auf einer gedämpften (siehe .tmdbTitleCard.notAdded) käme deren Deckkraft noch
   obendrauf und ließe ihn ganz verschwinden. */
.tmdbTitleCardRole {
	color: var(--text-muted);
	display: -webkit-box;
	font-size: 0.8rem;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

/* Noch nicht übernommene Vorschläge gedämpft, mit derselben Regel wie die fehlenden Filme einer Filmreihe (siehe
   .tmdbTile.notAdded) - inklusive des Aufhellens beim Überfahren bzw. Antippen. */
.tmdbTitleCard.notAdded {
	opacity: 0.55;
}

.tmdbTitleCard.notAdded:hover {
	opacity: 1;
}

/* "Siehe auch" (siehe inc/tmdbMeta.html#relatedSection) ------------------------------------------------------

   Die Karte ist ein Behälter, der Verweis eine durchsichtige Fläche darüber: So kann die Schaltfläche zum Lösen im
   Poster sitzen (ein <button> darf nicht in einem <a> stehen) und trotzdem die ganze Karte auf die Detailseite
   führen - Titel und Meta-Zeile eingeschlossen, wie bei den übrigen Kartenreihen auch. */
.tmdbRelatedCard {
	position: relative;
}

.tmdbRelatedCardLink {
	inset: 0;
	position: absolute;
}

/* Symbol und Text der Überschrift auseinanderhalten - der Text schließt sonst unmittelbar an die Kette an. Nur
   hier, weil die übrigen Kartenreihen keine Überschrift mit Symbol tragen. */
.tmdbRelatedHeading {
	align-items: center;
	display: flex;
	gap: 0.45rem;
}

/* Sagt, ob der Verweis auf einen Film, eine Filmreihe oder eine Serie zeigt - in dieser Reihe stehen alle drei
   gemischt. Unten links, weil oben je nach Eintrag schon "gesammelt" und "gesehen" stehen und unten rechts das
   Lösen-Zeichen sitzt. Gedämpftes Grau statt einer eigenen Farbe: Die Angabe ordnet nur ein, sie meldet nichts. */
.tmdbBadge.tmdbTypeMark {
	bottom: 0.4rem;
	color: #aab;
	left: 0.4rem;
	position: absolute;
}

/* Unten rechts im Poster, gegenüber den Kennzeichen oben. Dauerhaft sichtbar und nicht erst beim Überfahren:
   Am Tablet - dem hauptsächlichen Gerät - gibt es kein Überfahren, die Schaltfläche wäre dort nicht auffindbar.
   Zurückhaltend genug, um das Poster nicht zu stören, und beim Überfahren deutlich.

   z-index über der Verweis-Fläche (siehe .tmdbRelatedCardLink), sonst läge diese darüber und finge den Klick ab. */
.tmdbRelatedRemoveBtn {
	align-items: center;
	background: rgba(17,17,51,0.85);
	border: none;
	border-radius: 50%;
	bottom: 0.4rem;
	color: #bbc;
	cursor: pointer;
	display: flex;
	font-size: 0.8rem;
	height: 1.6rem;
	justify-content: center;
	padding: 0;
	position: absolute;
	right: 0.4rem;
	width: 1.6rem;
	z-index: 1;
}

.tmdbRelatedRemoveBtn:hover {
	background: rgba(51,17,17,0.95);
	color: #f88;
}

/* Die Karte zum Hinzufügen ist als einzige der Reihe eine Schaltfläche, und die zentriert ihren Inhalt senkrecht.
   Da sie nur das Poster-Feld trägt (ohne Titel und Meta-Zeile), säße dieses sonst mittig neben den Postern der
   übrigen Karten statt auf gleicher Höhe. Als Spalte mit Ausrichtung nach oben beginnt ihr Inhalt wieder oben.

   Gilt nur für die Karte in der Reihe - derselbe Klassenname sitzt auch am Menüpunkt "Inhalte verknüpfen...",
   der ein gewöhnlicher Eintrag im "..."-Menü ist und dessen Aussehen behalten muss. */
.tmdbTitleCardRow .tmdbRelatedAddBtn {
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
}

/* Kein Poster, sondern ein gestrichelter Rahmen im Posterformat, damit die Reihe gleich hoch bleibt (Muster wie
   .tmdbTile.tmdbTileMuted). */
.tmdbRelatedAddPoster {
	align-items: center;
	aspect-ratio: 2 / 3;
	background: transparent;
	border: 2px dashed var(--line-subtle);
	border-radius: 8px;
	color: var(--text-muted);
	display: flex;
	font-size: 1.8rem;
	justify-content: center;
	width: 100%;
}

.tmdbRelatedAddBtn:hover .tmdbRelatedAddPoster {
	border-color: var(--text-muted);
	color: var(--text);
}

/* Trefferzeile im Verknüpfen-Dialog: Kontrollkästchen und Art-Zeichen links, Titel und Untertitel rechts daneben.
   Die Grundzeile ist eine Spalte (siehe .tmdbLinkResult), hier wird daraus eine Zeile mit eigener Textspalte.

   Die Zeile ist ein <label> zu einem unsichtbaren Kästchen (siehe .defaultCheckbox), damit ein Klick irgendwo in
   der Zeile umschaltet - nicht nur auf ein kleines Kästchen. */
.tmdbRelatedResult {
	align-items: center;
	flex-direction: row;
	gap: 0.6rem;
}

/* Das Kästchen wird vom Label gezeichnet, mit denselben Maßen und Farben wie .defaultCheckboxLabel::before -
   bewusst nachgebildet statt jene Regel mitzubenutzen: Die trägt eine Pillen-Optik (Rahmen, Polsterung,
   inline-flex), die einer Zeile über die volle Dialogbreite nicht steht. */
.tmdbRelatedResult::before {
	background-color: var(--page-bg);
	border: 1px solid var(--control-border);
	border-radius: 4px;
	content: "";
	display: inline-flex;
	flex-shrink: 0;
	height: 1em;
	justify-content: center;
	line-height: 1em;
	width: 1em;
}

.defaultCheckbox:checked + .tmdbRelatedResult::before {
	background-color: var(--control-border);
	color: #fff;
	content: "✓";
	font-weight: bold;
}

/* Angehakte Zeile wie eine ausgewählte hervorheben (dieselben Farben wie .tmdbLinkResult.active): */
.defaultCheckbox:checked + .tmdbRelatedResult {
	background: var(--control-bg-hover);
	color: var(--control-text-hover);
}

.defaultCheckbox:checked + .tmdbRelatedResult .tmdbLinkResultDesc,
.defaultCheckbox:checked + .tmdbRelatedResult .tmdbRelatedResultIcon {
	color: #dde;
}

/* Die getroffene Auswahl über den Schaltflächen - sie zeigt auch das, was nach einer neuen Suche nicht mehr in der
   Trefferliste steht, und ist der einzige Weg, es dort wieder herauszunehmen. */
.tmdbRelatedPicked {
	border-top: 1px solid var(--line-subtle);
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin-top: 0.6rem;
	padding-top: 0.6rem;
}

/* Zwingend, sonst gewinnt das display:flex darüber gegen das display:none, das der Browser dem hidden-Attribut
   mitgibt - der leere Kasten stünde dann mit Trennlinie und Polsterung über den Schaltflächen. */
.tmdbRelatedPicked[hidden] {
	display: none;
}

.tmdbRelatedPick {
	align-items: center;
	background: var(--control-bg);
	border: 1px solid var(--control-border);
	border-radius: var(--control-radius);
	display: inline-flex;
	font-size: 0.85rem;
	gap: 0.35rem;
	max-width: 100%;
	padding: 0.2rem 0.3rem 0.2rem 0.5rem;
}

/* Lange Titel abschneiden statt die Pille über die Dialogbreite wachsen zu lassen: */
.tmdbRelatedPick > span {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.tmdbRelatedPick > button {
	background: none;
	border: none;
	color: var(--text-muted);
	cursor: pointer;
	display: flex;
	font-size: 0.9em;
	padding: 0.1rem;
}

.tmdbRelatedPick > button:hover {
	color: #f88;
}

/* "Auch untereinander verknüpfen" samt Ansage, wie viele Verknüpfungen daraus werden. Wie bei .tmdbRelatedPicked
   muss das display:none für das hidden-Attribut ausdrücklich gesetzt werden, sonst gewinnt das display:flex. */
.tmdbRelatedCrossRow {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-top: 0.6rem;
}

.tmdbRelatedCrossRow[hidden] {
	display: none;
}

.tmdbRelatedCrossHint {
	color: var(--text-muted);
	font-size: 0.8rem;
}

.tmdbRelatedResultText {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	min-width: 0;
}

/* Dieselbe zurückgenommene Farbe wie die Zeile darunter: Das Zeichen ordnet den Treffer ein, es ist nicht der
   Treffer selbst. Feste Breite, damit die Titel aller Zeilen bündig beginnen, auch wenn die Zeichen unterschiedlich
   breit sind. */
.tmdbRelatedResultIcon {
	color: #99a;
	flex: none;
	font-size: 1.25rem;
	text-align: center;
	width: 1.5rem;
}

/* Auf der ausgewählten Zeile mit aufhellen, sonst fiele das Grau auf dem helleren Untergrund ab (wie
   .tmdbLinkResult.active .tmdbLinkResultDesc). */
.tmdbLinkResult.active .tmdbRelatedResultIcon {
	color: #dde;
}

/* Erklärt im Verknüpfen-Dialog die beiden Eigenheiten, die man sonst erst durch Ausprobieren merkt: dass nur
   Vorhandenes verknüpfbar ist und dass die Verknüpfung beidseitig gilt (siehe inc/tmdbRelatedDialog.html). */
.tmdbRelatedHint {
	color: var(--text-muted);
	font-size: 0.8rem;
	margin: 0.4rem 0 0 0;
}

/* Eine Kartenreihe, die in jeder Breite eine Zeile hoch bleibt (siehe inc/tmdbMeta.html#titleCardSection, Parameter
   singleRow) - dieselbe Mechanik wie bei den Videos und aus demselben Grund: TMDBs Vorschläge stehen am Seitenende
   und sollen nicht umbrechend mehrere Bildschirmhöhen füllen. Die angeschnittene nächste Karte am rechten Rand
   zeigt an, dass es weitergeht. */
.tmdbTitleCardSectionSingle .tmdbTitleCardRow {
	flex-wrap: nowrap;
	overflow-x: auto;
	padding-bottom: 0.5rem;
	scroll-snap-type: x proximity;
}

.tmdbTitleCardSectionSingle .tmdbTitleCard {
	scroll-snap-align: start;
}

/* Auf der Startseite gilt das Wischen in jeder Breite, nicht nur am Handy: Dort stehen mehrere Reihen
   untereinander ("Neue Filme", "Neue Serien", "Zuletzt hinzugefügt"), und jede soll genau eine Zeile hoch sein -
   sonst schöbe eine einzelne umbrechende Reihe die folgenden aus dem Bild. Auf den Detailseiten bleibt es beim
   Umbruch, dort steht nur eine Reihe am Seitenende (siehe index.html, .homeCardRows).

   Die Regeln stehen bewusst hier statt in der 640px-Query darunter: So gewinnen sie dort nicht per Reihenfolge,
   sondern gelten schlicht immer - die Query bleibt für alle übrigen Reihen zuständig. */
.homeCardRows .tmdbTitleCardRow {
	flex-wrap: nowrap;
	overflow-x: auto;
	padding-bottom: 0.5rem;
	scroll-snap-type: x proximity;
}

.homeCardRows .tmdbTitleCard {
	scroll-snap-align: start;
}

/* Jede Reihe der Startseite bekommt denselben Karteireiter wie die Bereichsmarke darüber, nur in Grau: Fläche
   allein hinter der Überschrift, Unterkante als Linie weiter nach rechts. Die Linie endet an der Breite der
   Reihe - bei den nebeneinanderstehenden Kategorien zeichnet sie damit zugleich deren Spalte nach.

   Bewusst nur hier: Auf den Detailseiten ("Ähnliche Filme") und der Personenseite steht dasselbe Makro, dort
   bleibt es bei der schlichten Überschrift.

   Etwas kleiner als eine gewöhnliche Überschrift (Vorgabe des Browsers ist rund 1,17rem): Der Reiter benennt hier
   nur eine Reihe innerhalb eines Bereichs und steht damit eine Stufe unter dessen Marke - zwischen deren 0,85rem
   und der vollen Überschriftengröße. */
.homeCardRows .tmdbTitleCardSection h3 {
	border-bottom: 2px solid var(--home-row-label-color);
	display: block;
	font-size: 1rem;
	margin-bottom: 0.8rem;
}

.homeCardRows .tmdbTitleCardHeadingInner {
	align-items: center;
	background: var(--home-row-label-color);
	border-radius: 6px 6px 0 0;
	color: #fff;
	display: inline-flex;
	gap: 0.5rem;
	padding: 0.15rem 0.8rem;
}

/* Auf dem Reiter nie unterstreichen (die Vorgabe von .tmdbTitleCardHeadingLink): Eine Unterstreichung mitten
   auf der Fläche sähe nach Textlink aus und liefe zudem der Reiterkante darunter zuwider. Dass es anklickbar
   ist, zeigt stattdessen die aufgehellte Fläche - dieselbe Rückmeldung wie bei den Kacheln. */
.homeCardRows .tmdbTitleCardHeadingInner:hover {
	text-decoration: none;
}

.homeCardRows a.tmdbTitleCardHeadingInner:hover {
	filter: brightness(1.2);
}

/* Auf der farbigen Fläche taugt das Grau der Meta-Angaben nicht mehr - das Gruppensymbol tritt hier über eine
   abgeschwächte Weißstufe zurück, damit es gedämpft bleibt, ohne im Reiter zu verschwinden. */
.homeCardRows .tmdbTitleCardHeadingInner .tmdbTitleCardGroupIcon {
	color: rgba(255, 255, 255, 0.65);
}

/* Marke über den beiden Bereichen der Startseite ("Kategorien" und "Neues"): Sie benennt den Unterschied
   zwischen selbst zusammengestellten und automatisch gefüllten Reihen, der aus den Reihentiteln allein nicht
   hervorgeht.

   Beschriftet wie die senkrechten Balken der Gruppenkacheln darüber (siehe .tile-group-label), nur waagerecht.
   Die Fläche liegt bewusst nur hinter dem Text - als Karteireiter, dessen Unterkante sich als Linie über die
   ganze Breite fortsetzt. Eine durchgehend farbige Zeile wäre für eine bloße Bereichsmarke zu schwer. */
.homeRowsLabel {
	border-bottom: 2px solid var(--home-label-color);
	margin: 1.2rem 0 0 0;
}

.homeRowsLabel > span {
	background: var(--home-label-color);
	border-radius: 6px 6px 0 0;
	color: #fff;
	display: inline-block;
	font-size: 0.85rem;
	font-weight: bold;
	letter-spacing: 0.2em;
	padding: 0.2rem 0.9rem;
	text-transform: uppercase;
}

/* Die erste Reihe eines Bereichs bringt ihren eigenen Abstand mit (.tmdbTitleCardSection hat margin-top), der
   hier überschrieben wird: Unter der Marke steht bewusst mehr Luft als über ihr - die durchgezogene Linie hält
   den Bezug zum Bereich darunter ohnehin, während oben der Abstand zum vorigen Bereich genügt. */
.homeRowsLabel + * .tmdbTitleCardSection,
.homeRowsLabel + .tmdbTitleCardSection {
	margin-top: 1rem;
}

/* Kategorien sind oft kurz (zwei, drei Titel) und verschwendeten als eigene Zeile viel Platz. Sie stehen deshalb
   nebeneinander, sobald zwei nebeneinander passen.

   Ein Umbruch per flex-wrap reichte dafür nicht: Er kann nur der Reihe nach umbrechen, eine lange Kategorie in der
   Mitte zerriss also die kurzen um sie herum. Das Raster mit "dense" darf dagegen zurückgreifen und holt eine
   spätere kurze Reihe in eine Lücke, die eine lange vor ihr gelassen hat - die Reihenfolge der Kategorien bleibt
   damit die Vorgabe, ohne dass Löcher entstehen.

   Die Spalte ist eine Karte breit, der Abstand genau der zwischen zwei Karten (siehe .tmdbTitleCard und
   .tmdbTitleCardRow): Nur so deckt sich eine Spannweite von n Spalten ungefähr mit n Karten.

   minmax(..., 1fr) statt einer starren Breite, damit die Spalten den Rest unter sich aufteilen, der am rechten
   Rand nicht mehr für eine weitere reicht. Mit starren 7,5rem blieb er ungenutzt liegen, und eine Reihe über die
   volle Breite endete dadurch sichtbar früher als die Reihen darunter, die kein Raster verwenden. */
.homeCategoryRows {
	display: grid;
	gap: 0 0.8rem;
	grid-auto-flow: row dense;
	grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
}

/* Die Spannweite kommt als --span aus dem Template (eine Spalte je Karte, siehe HomeCategory#getColumnSpan). */
.homeCategoryCell {
	grid-column: span var(--span, 2);
	min-width: 0;
}

/* Lange Reihen nehmen die ganze Zeile, statt über viele Spalten zu spannen: Eine Spannweite größer als die
   Spaltenzahl ließe das Raster zusätzliche Spalten anlegen und die Seite seitlich überlaufen. "1 / -1" kann
   dagegen nie zu breit werden. */
.homeCategoryCell--full {
	grid-column: 1 / -1;
}

/* Ohne das schrumpfte eine Reihe nicht unter ihre Inhaltsbreite und liefe über den Rand, statt zu wischen. */
.homeCategoryCell .tmdbTitleCardSection {
	min-width: 0;
}

@media (max-width: 640px) {
	.tmdbTitleCardRow {
		flex-wrap: nowrap;
		overflow-x: auto;
		padding-bottom: 0.5rem;
		scroll-snap-type: x proximity;
	}

	.tmdbTitleCard {
		scroll-snap-align: start;
	}

	/* Am Handy reicht die Breite für kein Nebeneinander: Jede Kategorie bekommt ihre Zeile, wie vor dem Raster.
	   Nötig auch deshalb, weil bei nur einer Rasterspalte eine Spannweite von zwei eine zusätzliche anlegte. */
	.homeCategoryCell {
		grid-column: 1 / -1;
	}
}

/* Der Übernehmen-Knopf im Detail-Popup, mit Abstand zum Text darüber: */
.tmdbDetailActions {
	margin-top: 0.8rem;
}

/* Personenseite --------------------------------------------------------------------------------- */

/* Das Foto steht wie das Poster der Filmdetailseite fest links neben den Angaben - deshalb nutzt die Seite auch
   deren .tmdbMovieDetailHero/.tmdbMovieDetailInfo, und hier ist nur die Breite zu setzen: */
.tmdbPersonPhoto {
	flex: none;
	width: 13rem;
}

.tmdbPersonPhoto img,
.tmdbPersonPhoto .tmdbPosterPlaceholder {
	aspect-ratio: 2 / 3;
	border-radius: 8px;
	object-fit: cover;
	width: 100%;
}

/* Biografien sind lang - begrenzte Zeilenlänge hält sie lesbar, statt sie über die volle Fensterbreite zu ziehen: */
.tmdbPersonBio {
	max-width: 70rem;
}



/* TMDB-/Trailer-Links auf den Detailseiten (Serie, Staffel, Filmreihe, Film) - größer als in den Kacheln und als
   Pills. Sie stehen am Ende der Meta-Zeile, daher inline-flex statt flex: als Block würden sie die Zeile sprengen. */
.tmdbDetailLinks {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin-left: 0.6rem;
	vertical-align: middle;
}

.tmdbDetailLinks .tmdbExternalLink {
	background: #1b2b52;
	border: 1px solid #4a70b0;
	border-radius: 999px;
	color: #cfe0f5;
	font-size: 0.9rem;
	gap: 0.35rem;
	padding: 0.4rem 0.9rem;
}

.tmdbDetailLinks .tmdbExternalLink:active {
	background: #2a4383;
	border-color: #7aa0e0;
	color: #fff;
}

/* Die Trailer-Pille behält ihren roten Akzent (siehe .tmdbYoutubeLink), sonst wären beide Pillen nicht mehr
   auseinanderzuhalten - die Spezifität von .tmdbDetailLinks .tmdbExternalLink überschreibt ihn sonst: */
.tmdbDetailLinks .tmdbYoutubeLink {
	background: #4a1c28;
	border-color: #b04a5a;
	color: #ffcfd6;
}

.tmdbDetailLinks .tmdbYoutubeLink:active {
	background: #7a2c3e;
	border-color: #e07a8a;
	color: #fff;
}

/* Der "Links"-Auslöser ist ein <button> (für das .moreFlyout-Menü, siehe chrome.js) statt eines <a> wie TMDB/Trailer -
   ".actions button i" (siehe oben) würde dessen Icon sonst mit höherer Spezifität auf 1.2rem festnageln und es
   größer wirken lassen als die Nachbar-Icons: */
.tmdbDetailLinks .tmdbExternalLink i {
	font-size: inherit;
}

/* Einheitliche Optik im TMDB-/Kategorien-Bereich ------------------------------------------------- */

/* Die Formensprache dieses Bereichs kennt zwei Bausteine: die Pille mit Beschriftung und den runden Button mit
   nur einem Icon (siehe .tmdbCrumbBack, .tmdbTitleNav, .tmdbBurgerBtn, .tmdbDetailLinks). Farben überall
   gleich: #1b2b52 auf #4a70b0, beim Drücken #2a4383 auf #7aa0e0.

   Runder Icon-Button als wiederverwendbare Klasse, für Stellen ohne eigene Regel: */
.tmdbIconBtn {
	align-items: center;
	background: #1b2b52;
	border: 1px solid #4a70b0;
	border-radius: 50%;
	color: #cfe0f5;
	cursor: pointer;
	display: inline-flex;
	font-size: 1.1rem;
	height: 2rem;
	justify-content: center;
	padding: 0;
	width: 2rem;
}

.tmdbIconBtn:active,
.tmdbIconBtn.active {
	background: #2a4383;
	border-color: #7aa0e0;
	color: #fff;
}

/* Folgen-Karten: "Abspielen" und der TMDB-Link werden zu Pillen, die beiden reinen Icon-Schaltflächen rund.
   Eine Nummer kleiner als im Seitenkopf (1,75rem statt 2rem), weil sie auf der Karte zwischen Fließtext sitzen. */
.tmdbEpisodeActions {
	gap: 0.5rem;
}

.tmdbEpisodeActions .playMovie,
.tmdbEpisodeActions .streamMovie,
.tmdbEpisodeActions .streamExternal,
.tmdbEpisodeActions .tmdbExternalLink {
	background: #1b2b52;
	flex: 0 0 auto;
	white-space: nowrap;
	border: 1px solid #4a70b0;
	border-radius: 999px;
	color: #cfe0f5;
	font-size: 0.8rem;
	gap: 0.3rem;
	height: 1.75rem;
	padding: 0 0.8rem;
}

.tmdbEpisodeActions .playMovie:active,
.tmdbEpisodeActions .streamMovie:active,
.tmdbEpisodeActions .streamExternal:active,
.tmdbEpisodeActions .tmdbExternalLink:active {
	background: #2a4383;
	border-color: #7aa0e0;
	color: #fff;
}

/* Die drei runden Schaltflächen oben rechts in der Folgenkachel: Gesehen, Details, "..."-Menü. Sie standen bis zum
   03.09.2026 unten in der Aktionszeile zwischen den Abspiel-Knöpfen und wirkten dort verloren. */
.tmdbEpisodeInfoTop .actions .toggleMoreFlyout,
.tmdbEpisodeInfoTop .tmdbEpisodeDetailsBtn,
.tmdbEpisodeInfoTop .tmdbToggleWatchedBtn {
	align-items: center;
	background: #1b2b52;
	border: 1px solid #4a70b0;
	border-radius: 50%;
	color: #cfe0f5;
	display: inline-flex;
	height: 1.75rem;
	justify-content: center;
	padding: 0;
	width: 1.75rem;
}

.tmdbEpisodeInfoTop .actions .toggleMoreFlyout:active,
.tmdbEpisodeInfoTop .tmdbEpisodeDetailsBtn:active,
.tmdbEpisodeInfoTop .tmdbToggleWatchedBtn:active {
	background: #2a4383;
	border-color: #7aa0e0;
	color: #fff;
}

.tmdbEpisodeInfoTop .actions .toggleMoreFlyout i,
.tmdbEpisodeInfoTop .tmdbEpisodeDetailsBtn i,
.tmdbEpisodeInfoTop .tmdbToggleWatchedBtn i {
	font-size: 1rem;
}



/* Umwandlung nach MKV (siehe convert.js) -------------------------------------------------------- */

/* Was mit Bild und Ton passiert, als Aufzählung im Dialog - macht vorab sichtbar, ob Surround erhalten bleibt. */
.convertPlan {
	color: var(--control-text);
	font-size: 0.8rem;
	list-style: none;
	margin: 0.75rem 0 0 0;
	padding: 0;
}

.convertPlan li {
	padding: 0.15rem 0 0.15rem 1.1rem;
	position: relative;
}

.convertPlan li::before {
	color: var(--control-border-hover);
	content: "\2022";
	left: 0.25rem;
	position: absolute;
}

/* Bei YouTube-Downloads können bis zu 27 Sprachen in der .smi stecken - deshalb begrenzte Höhe mit Scrollen,
   damit der Dialog nicht über den Bildschirm hinauswächst. */
.convertLanguages {
	max-height: 11rem;
	margin-top: 0.25rem;
	overflow-y: auto;
}

/* Fortschrittsanzeige, die einen Seitenwechsel überlebt: fest am unteren Rand, über allem außer Dialogen. */
/* Gemeinsamer Kasten für laufende Hintergrundaufträge (MKV-Umwandlung, TMDB-Ordner-Scan) - siehe base.html. Beide
   Module rendern ihre Einträge in einen eigenen Unterbereich, liegen aber im selben Kasten, damit sie sich in der
   Ecke nicht überlagern. */
.jobProgress {
	background: var(--surface-dialog);
	border: 1px solid var(--line);
	border-radius: var(--field-radius);
	bottom: 1rem;
	box-shadow: 0 4px 16px rgba(0,0,0,0.5);
	left: 1rem;
	max-width: 22rem;
	padding: 0.6rem 0.75rem;
	position: fixed;
	z-index: 900;
}

.jobProgressEntry + .jobProgressEntry {
	margin-top: 0.6rem;
}

/* Gleicher Abstand auch zwischen den beiden Bereichen, wenn Umwandlung und Scan gleichzeitig laufen: */
#convertProgress:not(:empty) + #tmdbScanProgress:not(:empty) {
	margin-top: 0.6rem;
}

.jobProgressTitle {
	color: var(--control-text);
	display: block;
	font-size: 0.75rem;
	margin-bottom: 0.35rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Oben statt unten: unten überlagert ein fest positionierter Knopf auf schmalen Bildschirmen die Aktionsschaltflächen
   der letzten sichtbaren Tabellenzeile (z.B. Timer) und macht sie unerreichbar. Der Abstand richtet sich nach der
   4rem hohen Kopfzeile, die ihrerseits fixiert ist - siehe die engere Fassung für schmale Bildschirme unten.
   Ein-/Ausblenden per Klasse statt [hidden]: chrome.js schaltet "show" abhängig vom Scrollstand, und nur über
   opacity/visibility lässt sich das Erscheinen weich animieren statt abrupt zu springen. */
.scrollTopBtn {
	align-items: center;
	background: var(--surface-dialog);
	border: 1px solid var(--line);
	border-radius: 50%;
	box-shadow: 0 4px 16px rgba(0,0,0,0.5);
	color: var(--control-text);
	cursor: pointer;
	display: flex;
	font-size: 1.2rem;
	height: 2.75rem;
	justify-content: center;
	opacity: 0;
	pointer-events: none;
	position: fixed;
	right: 1rem;
	top: 4.75rem;
	transition: opacity 0.2s;
	visibility: hidden;
	width: 2.75rem;
	z-index: 9;
}

@media (max-width: 640px) {
	/* Die Kopfzeile ist hier nur 3rem hoch (siehe header), der Knopf rückt entsprechend näher heran. */
	.scrollTopBtn {
		top: 3.75rem;
	}
}

.scrollTopBtn.show {
	opacity: 1;
	pointer-events: auto;
	visibility: visible;
}

.jobProgressBar {
	background: var(--control-bg);
	border-radius: var(--control-radius);
	display: block;
	height: 0.4rem;
	overflow: hidden;
}

.jobProgressBarFill {
	background: var(--control-border-hover);
	display: block;
	height: 100%;
	transition: width 0.3s ease;
}

/* "Stoppen" unter dem Fortschrittsbalken des Ordner-Scans: klein und unaufdringlich, der Kasten ist nur eine
   Nebenanzeige. Rechtsbündig, damit er nicht wie eine Beschriftung des Balkens wirkt. */
.jobProgressActions {
	display: flex;
	justify-content: flex-end;
	margin-top: 0.4rem;
}

.jobProgressActions .defaultBtn {
	font-size: 0.72rem;
	padding: 0.2rem 0.5rem;
}

/* Warnung im Umwandeln-Dialog, wenn die Box das Bildformat gar nicht abspielen kann (siehe MediaInfo#getVideoWarning).
   Bewusst auffällig: Ohne sie verspricht der Dialog mit "wird unverändert übernommen" eine Lösung, die es nicht gibt. */
.convertWarning {
	background: rgba(200,120,40,0.14);
	border: 1px solid #c87828;
	border-radius: var(--field-radius);
	color: #f0c088;
	font-size: 0.78rem;
	margin: 0.75rem 0 0 0;
	padding: 0.5rem 0.6rem;
}
