diff --git a/dankserver/jellyfin/quadlet/jellyfin.container b/dankserver/jellyfin/quadlet/jellyfin.container index 318b712..ab15689 100644 --- a/dankserver/jellyfin/quadlet/jellyfin.container +++ b/dankserver/jellyfin/quadlet/jellyfin.container @@ -47,6 +47,12 @@ Volume=/home/dank/Containers/jellyfin/cache:/cache # is the guard: started against a plain, unmounted view directory a scan decides # the library is empty and deletes what it cannot see. Volume=/var/lib/media-meta/view:/data +# Big-screen theme for the TV. The repo file replaces the container's "Media +# Center" theme slot; the upstream dark palette stays live because the file +# @imports it, so an image bump cannot strand a vendored CSS snapshot. Read-only +# — the web app only fetches it. A client opts in with +# Display Settings -> Theme -> "Media Center". +Volume=/home/dank/serverAppConfigs/dankserver/jellyfin/theme/wmc/theme.css:/jellyfin/jellyfin-web/themes/wmc/theme.css:ro AddDevice=/dev/dri GroupAdd=keep-groups HealthCmd=curl -f http://localhost:8096/health diff --git a/dankserver/jellyfin/theme/wmc/theme.css b/dankserver/jellyfin/theme/wmc/theme.css new file mode 100644 index 0000000..bc4cd94 --- /dev/null +++ b/dankserver/jellyfin/theme/wmc/theme.css @@ -0,0 +1,53 @@ +/* + * Dank fleet big-screen theme for jellyfin-web. + * + * Deployed by bind-mounting THIS file over the container's "Media Center" + * theme (`/jellyfin/jellyfin-web/themes/wmc/theme.css`) — see the Volume line + * in dankserver/jellyfin/quadlet/jellyfin.container. The slot is deliberately + * one nobody picks by accident, and its name is the only thing that changes: + * the colors are the live upstream dark theme, pulled in by @import below, so + * this file never vendors a snapshot of upstream CSS and cannot drift when the + * Jellyfin image moves. + * + * Why it exists: the living-room client (Jellyfin Desktop on danklivingroom) + * renders this server-served web app at 3840x2160 with no client-side scaling, + * so 14 px body text lands on a big panel viewed from three metres. `zoom` on + * the root element is the one lever that scales the whole UI — the layout code + * measures layout px, so card grids re-flow to fewer, larger columns instead of + * overflowing. + * + * Adoption is per device, not global: Display Settings -> Theme -> + * "Media Center" on the screen that wants it. That is the point — a phone + * browser on the same server must not get a 1.75x interface. + * + * Change the size by editing the single number. 1.5 is mild, 1.75 is the + * three-metre default, 2.0 is for a projector. + */ + +@import url("../dark/theme.css"); + +:root { + /* Marker the e2e gate reads back; also a tweak hook for a per-client + override injected by anyone who really wants one. */ + --dank-big-screen: 1; + --dank-big-screen-zoom: 1.75; +} + +html { + zoom: var(--dank-big-screen-zoom); +} + +/* A remote moves focus in discrete jumps, so the ring has to survive a + three-metre read. */ +.emby-focus, +button:focus-visible, +a:focus-visible, +.inputElement:focus-visible { + outline: 3px solid var(--accentColor, #00a4dc) !important; + outline-offset: 2px !important; +} + +/* Scrollbars are mouse furniture; on a TV they are noise at this size. */ +* { + scrollbar-width: none; +} diff --git a/serverAppConfigs-docs/Dankserver/Jellyfin.md b/serverAppConfigs-docs/Dankserver/Jellyfin.md index ab0851a..36e5035 100644 --- a/serverAppConfigs-docs/Dankserver/Jellyfin.md +++ b/serverAppConfigs-docs/Dankserver/Jellyfin.md @@ -407,6 +407,41 @@ removed. Discover a route's verb from the `Allow` header of an `OPTIONS` (or Seerr keeps a key of its own in its own DB (which of its two rows it uses was never confirmed), so revoke by token and never by app name. +## Big-screen theme (the TV) + +`dankserver/jellyfin/theme/wmc/theme.css` is repo-owned and bind-mounted over the +image's **Media Center** theme slot (the `Volume=` line in +`dankserver/jellyfin/quadlet/jellyfin.container`). It exists for +`danklivingroom`, which renders this server-served web app at 3840×2160 with no +client-side scaling, so 14 px text arrives on a panel read from three metres. + +The file is four rules, and its first line is the design: +`@import url("../dark/theme.css")` pulls in the **live upstream** dark palette, so +the repo never vendors a CSS snapshot and a Jellyfin image bump cannot strand one. +That works because jellyfin-web applies a theme as +`` — a relative URL resolved +against the CSS file, not the document. The size lives in one number: +`--dank-big-screen-zoom` (1.75 ≈ three metres; 1.5 mild, 2.0 projector). `zoom` on +the root element is the right lever: the card-grid code measures layout pixels, so +fewer, larger columns are computed rather than overflow produced. + +- **Adoption is per device, and it stays that way.** The theme a client renders + comes from its own settings (localStorage first), so there is no server-side + "everyone gets the big UI" knob. On the screen that wants it: + **Display Settings → Theme → Media Center.** That is also the honest label — + the dropdown names are compiled into the bundle, so a "Big Screen" entry will + never appear; do not go looking for one. +- The mount is `:ro` and the app only fetches the file, so the failure mode of a + stale `@import` target is slightly wrong colors, never a dead web app. +- **Editing the CSS needs no restart.** The bind hands out the host file's live + bytes, so a changed zoom number is on screen at the next page load. The planner + agrees by construction: only `dankserver//quadlet/**` maps to a service, so + a `theme/**`-only commit plans nothing — that is correct, not a gap to "fix", + because restarting a media server for a font size is the wrong trade. Only the + first deploy of the `Volume=` line restarts anything. +- **Rollback is one line:** drop the `Volume=` and redeploy; nothing in the + database records the theme, so no cleanup follows. + ## See Also - [[Plex]] — co-resident media server on the same volume