fix(ui): a card's Play clears its hover row at a large text size; Downloads links and the player description

At text size 1.3 a 242px feed thumbnail put the 63px Play 13px into the
hover row (the Play grows with the root font, the picture's height does
not). A picture narrower than 14rem centres the Play and the resume pair
above the row; the picture box is a size container for it.

The Downloads title and channel links were 21px tall inline boxes; they
stand on a 24px line now (B1). The player's description says a failed
load, with a retry, instead of 'No description' (both the side panel
and the popover).
This commit is contained in:
2026-10-02 23:42:31 +02:00
parent 15ec67b029
commit e16cdbd16f
11 changed files with 112 additions and 18 deletions
+19 -3
View File
@@ -18,9 +18,21 @@ export const MEDIA_IMG =
export const MEDIA_BADGE =
"pointer-events-none absolute rounded-sm bg-black/80 px-1.5 py-0.5 text-2xs font-medium text-white tabular-nums";
/** The hover layer over the picture: a dim that carries the Play (mouse only, like the hover row). */
/** The picture box as a size container (`pic`), so what sits on the picture can answer its width.
* Every picture box carries it: `mediaPictureBox` and the video card's own box. */
export const MEDIA_PICTURE_CONTAINER = "@container/pic";
/** The hover layer over the picture: a dim that carries the Play (mouse only, like the hover row).
* On a narrow picture the Play centres in the band ABOVE the hover row instead of on the whole
* picture: the picture's height follows the card's width, but the Play and the row grow with the
* text size, so at 1.3 a 242px thumbnail put the 63px Play 13px into the 37px row (E31 S5,
* measured). The cut is in rem, so it moves with the text size too: a picture under 14rem wide. */
export const MEDIA_HOVER_LAYER =
"reveal-hover absolute inset-0 flex items-center justify-center gap-2 bg-black/45 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100";
"reveal-hover absolute inset-0 flex items-center justify-center gap-2 bg-black/45 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 @max-[14rem]/pic:pb-10";
/** The layer that holds a started title's Continue + Restart pair over the picture: a sibling of the
* picture's button, never inside it (C5). Narrow, it leaves the hover row its band as the Play does. */
export const MEDIA_RESUME_LAYER = `${HOVER_REVEAL} pointer-events-none absolute inset-0 z-base flex items-center justify-center gap-2 *:pointer-events-auto @max-[14rem]/pic:pb-10`;
/** Where the card's hover row (watched, save, add, "…") docks: the picture's bottom-right. */
export const MEDIA_BAR = `${HOVER_REVEAL} absolute bottom-2.5 right-1.5 z-base`;
@@ -39,4 +51,8 @@ export const mediaTitleClass = (dense: boolean, shelf = false) =>
/** The box that holds the picture at its ratio. `min-h-0`: an aspect-ratio box otherwise grows to
* its content's height, so a square channel avatar made a 16:9 slot square (measured 182×182). */
export const mediaPictureBox = (aspect: "poster" | "wide") =>
clsx("relative min-h-0", aspect === "poster" ? "aspect-2/3" : "aspect-video");
clsx(
"relative min-h-0",
MEDIA_PICTURE_CONTAINER,
aspect === "poster" ? "aspect-2/3" : "aspect-video",
);