fix(lyrics): allow line wrapping in fullscreen lyrics overlay

Increase slot height from 3.6vh → 6vh (CSS + JS factor 0.036 → 0.06)
so that long lyric lines can wrap onto a second line without being clipped.

Fixed height on .fs-lyric-line is kept intentional — rail math requires
uniform slots. 2 wrapped lines at 2vh font / 1.4 line-height = 5.6vh,
comfortably inside the 6vh slot. font-size adjusted from 2.2vh → 2vh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-04-07 12:36:06 +02:00
parent 8add62a502
commit fc653941c2
2 changed files with 14 additions and 10 deletions
+3 -3
View File
@@ -21,7 +21,7 @@ function formatTime(seconds: number): string {
}
// ─── Fullscreen lyrics overlay ────────────────────────────────────────────────
// Slot height = 3.6vh = window.innerHeight * 0.036 — must match CSS height: 3.6vh.
// Slot height = 6vh = window.innerHeight * 0.06 — must match CSS height: 6vh.
// railY = (2 - activeIdx) * slotH centers slot `activeIdx` in a 5-slot window:
// activeIdx=0 → railY=+2×slotH (line 0 at slot 2)
// activeIdx=2 → railY=0 (line 2 at center)
@@ -49,9 +49,9 @@ const FsLyrics = memo(function FsLyrics({ currentTrack }: { currentTrack: Track
const seek = usePlayerStore(s => s.seek);
// Cache slotH — avoids forcing a layout read (window.innerHeight) on every render.
const slotH = useRef(window.innerHeight * 0.036);
const slotH = useRef(window.innerHeight * 0.06);
useEffect(() => {
const onResize = () => { slotH.current = window.innerHeight * 0.036; };
const onResize = () => { slotH.current = window.innerHeight * 0.06; };
window.addEventListener('resize', onResize);
return () => window.removeEventListener('resize', onResize);
}, []);
+11 -7
View File
@@ -3250,19 +3250,19 @@
}
/* ── Lyrics overlay — upper-left quadrant, strictly 5 lines tall ── */
/* Slot = 3.6vh → 5 × 3.6vh = 18vh. JS reads window.innerHeight * 0.036. */
/* Slot = 6vh → 5 × 6vh = 30vh. JS reads window.innerHeight * 0.06. */
.fs-lyrics-overlay {
position: absolute;
top: 15vh; /* pushed down into the quadrant, clear of close button */
left: clamp(28px, 4vw, 64px);
right: 52%; /* stay out of portrait area */
height: 18vh; /* exactly 5 × 3.6vh — never grows, never overlaps cluster */
height: 30vh; /* exactly 5 × 6vh — never grows, never overlaps cluster */
z-index: 3;
overflow: hidden;
pointer-events: none;
contain: layout style; /* isolate reflows from rest of page */
/* Fade first and last slot (each 3.6/18 = 20% of container) */
/* Fade first and last slot (each 6/30 = 20% of container) */
-webkit-mask-image: linear-gradient(
to bottom,
transparent 0%,
@@ -3289,14 +3289,18 @@
transition: transform 500ms ease-out;
}
/* Each lyric slot is exactly 3.6vh — matches JS window.innerHeight * 0.036 */
/* Each lyric slot is exactly 6vh — matches JS window.innerHeight * 0.06.
Fixed height (not min-height) is intentional: keeps rail math correct
regardless of whether the text wraps or not. 2 wrapped lines of 2vh
font at 1.4 line-height = 5.6vh, comfortably inside the 6vh slot. */
.fs-lyric-line {
height: 3.6vh;
height: 6vh;
display: flex;
align-items: center;
overflow: hidden;
white-space: nowrap;
font-size: 2.2vh;
white-space: normal;
font-size: 2vh;
line-height: 1.4;
color: rgba(255, 255, 255, 0.22);
font-weight: 400;
cursor: pointer;