From 5020a7a1fba71014b4efa096a24f39754b102fe4 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Mon, 14 Sep 2026 16:10:31 +0200 Subject: [PATCH] =?UTF-8?q?Ein=20Flixy-Kleid=20f=C3=BCr=20Jellyfins=20Webo?= =?UTF-8?q?berfl=C3=A4che?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Für den Zugang von Windows aus, wo es keine App gibt und auch keine geben wird. Ein Kleid, kein Umbau. Variablennamen und Klassen stammen aus einer laufenden Jellyfin-Instanz, nicht aus dem Gedächtnis: Jellyfin baut auf einer MUI-Palette auf, und wer die umbiegt, erwischt auch Bauteile, die dieses CSS gar nicht kennt. Direkt überschrieben wird nur dort, wo Jellyfin an der Palette vorbei setzt — der Seitenhintergrund und die Kartenrundung tun das. Live gegen die öffentliche Jellyfin-Demo geprüft: Farben, Systemschrift, Kartenrundung, Akzent und die schwebende Kopfleiste greifen. Co-Authored-By: Claude Opus 5 --- web/jellyfin-theme/flixy.css | 334 +++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 web/jellyfin-theme/flixy.css diff --git a/web/jellyfin-theme/flixy.css b/web/jellyfin-theme/flixy.css new file mode 100644 index 0000000..0b0c581 --- /dev/null +++ b/web/jellyfin-theme/flixy.css @@ -0,0 +1,334 @@ +/* ============================================================================ + Flixy für Jellyfin Web + ---------------------------------------------------------------------------- + Bringt Jellyfins Weboberfläche auf die Farben, Schrift und Formen der + Flixy-App. Es ist ein Kleid, kein Umbau: die Oberfläche bleibt Jellyfins, + sie sieht nur anders aus. + + EINBAUEN + Jellyfin-Dashboard → Allgemein → „Benutzerdefiniertes CSS“ — alles hier + hineinkopieren, speichern, Seite neu laden. Gilt serverweit für alle + Browser, also auch auf Windows. Wieder loswerden: Feld leeren. + + AUFGEBAUT AUF MESSUNG, NICHT AUF VERMUTUNG + Die Variablennamen und Klassen stammen aus einer laufenden Jellyfin- + Instanz (Stand 09/2026), nicht aus dem Gedächtnis. Der größte Teil der + Wirkung entsteht dadurch, dass Jellyfins **eigene** Farbvariablen + umgebogen werden — das hält das Ganze kurz und überlebt Updates besser + als eine Sammlung einzeln überschriebener Regeln. + ========================================================================= */ + +:root { + /* ---- Die Akzentfarbe ----------------------------------------------- + Zum Wechseln nur diese eine Zeile ändern. Die Palette der App: + Ember #E5484D · Tangerine #F76B15 · Amber #FFB224 · Lime #99D52A + Mint #3DD68C · Teal #12A594 · Sky #52A9FF · Indigo #7C77E8 + Orchid #C04AC9 · Rose #F76190 + Voreingestellt ist Orchid — die Farbe, die auf dem iPad eingestellt + ist. Die App selbst kommt ab Werk mit Mint. */ + --flixy-accent: #C04AC9; + + /* ---- Die Flächen der App, von hinten nach vorn ---------------------- */ + --flixy-canvas: #0B0B0D; /* Seitenhintergrund */ + --flixy-surface: #141417; /* Karten, Kopfbereiche */ + --flixy-elevated: #1D1D21; /* Blätter, Menüs */ + --flixy-placeholder: #26262B; /* Platzhalter, gedrückte Zustände */ + + --flixy-text: #F5F5F7; + --flixy-text-secondary: #A0A0A8; + --flixy-text-muted: #6E6E76; + --flixy-destructive: #E5484D; + --flixy-separator: rgba(255, 255, 255, 0.10); + + /* ---- Formen --------------------------------------------------------- */ + --flixy-radius-card: 8px; + --flixy-radius-control: 10px; + --flixy-radius-sheet: 16px; + --flixy-radius-panel: 22px; /* die schwebende Leiste */ + + /* ---- Schrift -------------------------------------------------------- + Der größte einzelne Hebel. Jellyfin liefert Noto Sans aus; die + Systemschrift macht aus derselben Seite sofort eine, die auf den + Rechner gehört — SF auf Mac und iPhone, Segoe UI Variable auf + Windows 11. */ + --flixy-font: -apple-system, BlinkMacSystemFont, "SF Pro Text", + "Segoe UI Variable Text", "Segoe UI", system-ui, + Roboto, "Helvetica Neue", sans-serif; + + /* ---- Jellyfins eigene Variablen umbiegen --------------------------- + Hier entsteht der Großteil der Wirkung: Jellyfin baut auf einer + MUI-Palette auf, und wer die verstellt, verstellt alles, was darauf + aufsetzt — inklusive Bauteilen, die dieses CSS gar nicht kennt. */ + --jf-palette-background-default: var(--flixy-canvas); + --jf-palette-background-defaultChannel: 11 11 13; + --jf-palette-background-paper: var(--flixy-surface); + --jf-palette-background-paperChannel: 20 20 23; + + --jf-palette-primary-main: var(--flixy-accent); + --jf-palette-primary-dark: var(--flixy-accent); + --jf-palette-primary-light: var(--flixy-accent); + --jf-palette-secondary-main: var(--flixy-accent); + --jf-palette-secondary-dark: var(--flixy-accent); + --jf-palette-secondary-light: var(--flixy-accent); + /* Schrift auf dem Akzent: hell, weil die Palette der App durchweg + kräftige Farben hat. Bei einem hellen Akzent (Amber, Lime) hier auf + #101013 stellen, sonst verschwindet die Beschriftung. */ + --jf-palette-primary-contrastText: #FFFFFF; + --jf-palette-secondary-contrastText: #FFFFFF; + + --jf-palette-text-primary: var(--flixy-text); + --jf-palette-text-secondary: var(--flixy-text-secondary); + --jf-palette-text-disabled: var(--flixy-text-muted); + --jf-palette-text-icon: var(--flixy-text-secondary); + --jf-palette-divider: var(--flixy-separator); + + --jf-palette-error-main: var(--flixy-destructive); + --jf-palette-error-dark: #B4373B; + --jf-palette-error-light: #EC6E72; + + --jf-palette-action-hover: rgba(255, 255, 255, 0.06); + --jf-palette-action-selected: rgba(255, 255, 255, 0.12); + --jf-palette-action-disabled: var(--flixy-text-muted); + + /* Die Kopfleiste trägt die Insel — sie selbst bleibt durchsichtig. */ + --jf-palette-AppBar-defaultBg: transparent; + --jf-palette-AppBar-darkBg: transparent; + + --jf-card-borderRadius: var(--flixy-radius-card); + --jf-shape-borderRadius: var(--flixy-radius-control); +} + +/* ---- Grundfläche und Schrift -------------------------------------------- + `html` bekommt seinen Hintergrund bei Jellyfin unmittelbar gesetzt und + nicht über die Palette — deshalb steht er hier noch einmal ausdrücklich. */ +html { + background-color: var(--flixy-canvas) !important; + font-family: var(--flixy-font) !important; + color: var(--flixy-text); +} + +body, +button, +input, +select, +textarea, +.emby-button, +.emby-input, +.emby-select, +.cardText, +.sectionTitle { + font-family: var(--flixy-font) !important; +} + +.backgroundContainer, +.mainAnimatedPage { + background-color: var(--flixy-canvas) !important; +} + +/* ---- Die Kopfleiste als schwebende Insel -------------------------------- + Das Merkmal der App: die Navigation ist eine Fläche mit Abstand ringsum, + nicht ein Balken, der am Rand klebt. Der Inhalt läuft dahinter durch. + + `backdrop-filter` ist der Kern — und der Grund, warum es auf Safari und + Chrome überzeugender aussieht als auf älteren Firefox-Fassungen. Wo er + fehlt, bleibt eine schlicht gefüllte Fläche; unschön ist das nicht. */ +.skinHeader { + background: rgba(20, 20, 23, 0.72) !important; + backdrop-filter: saturate(180%) blur(20px); + -webkit-backdrop-filter: saturate(180%) blur(20px); + border: 1px solid var(--flixy-separator); + border-radius: var(--flixy-radius-panel); + margin: 10px 12px 0; + width: calc(100% - 24px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45); +} + +.skinHeader-withBackground { + background: rgba(20, 20, 23, 0.72) !important; +} + +/* ---- Die Seitenleiste ---------------------------------------------------- */ +.mainDrawer { + background-color: var(--flixy-surface) !important; + border-right: 1px solid var(--flixy-separator); +} + +.navMenuOption { + border-radius: var(--flixy-radius-control); + margin: 2px 8px; +} + +.navMenuOption-selected { + background: var(--flixy-elevated) !important; + color: var(--flixy-accent) !important; +} + +/* ---- Karten ------------------------------------------------------------- + Die Poster sind das, was man auf einer Startseite hauptsächlich sieht; + ihre Rundung bestimmt den Eindruck stärker als jede Farbe. Acht Punkt, + wie in der App. */ +.cardImageContainer, +.cardContent, +.cardScalable, +.cardOverlayContainer { + border-radius: var(--flixy-radius-card) !important; +} + +.cardBox { + margin: 0.5em !important; +} + +.cardText { + color: var(--flixy-text); +} + +.cardText-secondary { + color: var(--flixy-text-secondary); +} + +.defaultCardBackground, +.defaultCardBackground1, +.defaultCardBackground2, +.defaultCardBackground3, +.defaultCardBackground4, +.defaultCardBackground5 { + background-color: var(--flixy-placeholder) !important; +} + +/* Der Fortschrittsbalken auf angefangenen Titeln — in der App trägt er den + Akzent, und er ist dünner als Jellyfins Voreinstellung. */ +.itemProgressBarForeground { + background-color: var(--flixy-accent) !important; +} + +.itemProgressBar { + height: 3px !important; + border-radius: 2px; + background-color: rgba(255, 255, 255, 0.18) !important; +} + +/* ---- Knöpfe -------------------------------------------------------------- */ +.emby-button, +.button-flat, +.detailButton { + border-radius: var(--flixy-radius-control) !important; + font-family: var(--flixy-font) !important; +} + +.emby-button.raised { + background: var(--flixy-elevated); + color: var(--flixy-text); +} + +.emby-button.raised.button-submit, +.button-submit { + background: var(--flixy-accent) !important; + color: #FFFFFF !important; +} + +/* Die Kapselform der App für die Hauptknöpfe einer Detailseite. */ +.detailPagePrimaryContainer .emby-button, +.mainDetailButtons .emby-button { + border-radius: 999px !important; +} + +/* ---- Eingabefelder ------------------------------------------------------- */ +.emby-input, +.emby-select, +.emby-textarea { + background-color: var(--flixy-elevated) !important; + border: 1px solid var(--flixy-separator) !important; + border-radius: var(--flixy-radius-control) !important; + color: var(--flixy-text) !important; +} + +.emby-input:focus, +.emby-select:focus { + border-color: var(--flixy-accent) !important; + outline: none; +} + +.inputLabel, +.selectLabel, +.fieldDescription { + color: var(--flixy-text-secondary) !important; +} + +/* ---- Blätter, Menüs, Dialoge --------------------------------------------- */ +.dialog, +.formDialog, +.actionSheet, +.paper-icon-button-light + .actionSheet { + background-color: var(--flixy-elevated) !important; + border-radius: var(--flixy-radius-sheet) !important; + border: 1px solid var(--flixy-separator); +} + +.actionSheetMenuItem:hover, +.listItem:hover { + background-color: var(--jf-palette-action-hover) !important; +} + +/* ---- Detailseite --------------------------------------------------------- */ +.detailPagePrimaryContainer, +.detailPageSecondaryContainer, +.detailRibbon { + background: transparent !important; +} + +.detailSectionContent, +.detailTableBodyCell { + color: var(--flixy-text-secondary); +} + +/* Das Hintergrundbild soll nach unten in die Seitenfarbe auslaufen, statt an + einer Kante aufzuhören — dieselbe Verlaufsidee wie im Aufmacher der App. */ +.itemBackdrop { + -webkit-mask-image: linear-gradient(to bottom, + rgba(0, 0, 0, 1) 0%, + rgba(0, 0, 0, 0.85) 45%, + rgba(0, 0, 0, 0) 100%); + mask-image: linear-gradient(to bottom, + rgba(0, 0, 0, 1) 0%, + rgba(0, 0, 0, 0.85) 45%, + rgba(0, 0, 0, 0) 100%); +} + +/* ---- Überschriften ------------------------------------------------------- */ +.sectionTitle { + color: var(--flixy-text) !important; + font-weight: 600; + letter-spacing: -0.01em; +} + +/* ---- Trennlinien und Kleinkram ------------------------------------------- */ +.listItem-border, +.detailTableBodyCell, +hr { + border-color: var(--flixy-separator) !important; +} + +::selection { + background: var(--flixy-accent); + color: #FFFFFF; +} + +/* Die Bildlaufleisten dunkel halten — eine helle Leiste am Rand ist das + Erste, was eine sonst dunkle Seite verrät. */ +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.14); + border-radius: 999px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.22); +}