diff --git a/docs/mockups/07-service-lyrics-spacing.html b/docs/mockups/07-service-lyrics-spacing.html new file mode 100644 index 0000000..a8f857b --- /dev/null +++ b/docs/mockups/07-service-lyrics-spacing.html @@ -0,0 +1,1525 @@ + + + + + + YT Player — Service Mode Lyrics Redesign Mockup + + + + + + +
+ +
+
+ ▶ YT Player +
+
MOCKUP 07 · SERVICE MODE LYRICS REDESIGN
+
+ + +
+
Service Mode · Full-Screen Lyrics Spacing & Type Floor
+

Legible Stage & Sanctuary Lyrics: Hard Floor Font Size & Generous Spacing

+

+ Real implementation: frontend/styles.css (.sl-line, .sl-list) and frontend/index.html (#serviceMode). + Eliminates unreadable 10–12px micro-text when songs have long lines. Rather than shrinking the font until the whole sentence fits on one row, this redesign enforces a hard minimum floor (min 22px on mobile) and gracefully wraps to 2 lines with balanced typography. Combined with generous breathing room (clamp(14px, 3.2vh, 40px)) and an accent-tinted glowing pill on the active sung line, musicians and vocalists can lead with effortless visual confidence. +

+
+ + +
+ + +
+ +
+
+ ✕ BEFORE · UNFLOORED FIT CALCULATION + Cramped single-row force +
+ +
+
+
Amazing grace, how sweet the sound
+
That saved a wretch like me
+
+ The Lord has promised good to me, His word my hope secures, He will my shield and portion be +
+
As long as life endures
+
+
+ +
+
+ Long Line Font + ~11.2px +
+
+ Line Spacing Gap + 4px (cramped) +
+
+ Stage Stand Read + Unreadable (>1m) +
+
+
+ + +
+
+ ✓ AFTER · HARD ≥ 22PX FLOOR + 2-LINE WRAP + SPACED + Legible stage typography +
+ +
+
+
Amazing grace, how sweet the sound
+
+ The Lord has promised good to me,
His word my hope secures +
+
As long as life endures
+
+
+ +
+
+ Long Line Font + 28px (wrapped) +
+
+ Line Spacing Gap + clamp(14px, 3.2vh, 40px) +
+
+ Stage Stand Read + Clear at 2.5m +
+
+
+
+
+ + +
+ 💡 Interactive Mockup: Tap any lyric line on the phone or projector to change the active sung line in real-time. +
+ + +
+ + +
+ +
+
+ 📱 Mobile Viewport · 390 × 844 px (iPhone Stand) +
+ +
+
+ +
+
+
+
+ + +
+ 9:41 +
+ 5G + 􀙇 + 100% +
+
+ + +
+ +
+
+
+

Amazing Grace

+
+ + Key of G · 3/4 · John Newton +
+
+ +
+ +
+ + + Set 2 / 5 +
+
+ + +
+
+ +
+ Amazing grace, how sweet the sound +
+ + +
↕ clamp(14px, 3.2vh, 40px) [~26px]
+ + +
+ That saved a wretch like me +
+ + +
↕ clamp(14px, 3.2vh, 40px) [~26px]
+ + +
+ + I once was lost, but now I'm found +
+ + +
↕ clamp(14px, 3.2vh, 40px) [~26px]
+ + +
+ The Lord has promised good to me, His word my hope secures +
+ ↳ Wraps to 2 lines · 25px (Never shrinks to 11px) +
+
+ + +
↕ clamp(14px, 3.2vh, 40px) [~26px]
+ + +
+ 'Twas grace that taught my heart to fear +
+
+
+ + +
+
+
+
+
+
+
+ 02:14 + AMAZING GRACE + 04:30 +
+
+ +
+ + + +
+ +
+
+
+
+
+
+ + +
+
+ 📽 Wide 16:9 Projector Frame · Sanctuary Broadcast Output +
+ +
+ +
+
+ Amazing Grace + VERSE 1 / 4 +
+
+ 1080p 60Hz +
+ + LIVE ON PROJECTOR +
+
+
+ + +
+ +
+ Amazing grace, how sweet the sound +
+ + +
+ That saved a wretch like me +
+ + +
+ I once was lost, but now I'm found +
+ + +
+ The Lord has promised good to me, His word my hope secures +
+ + +
+ 'Twas grace that taught my heart to fear +
+
+ + + +
+ + +
+ Projector Target: 1920 × 1080 (16:9 Aspect) + Spacing: clamp(18px, 4.2vh, 46px) +
+
+
+
+ + +
+ 03 · Architectural Design Specifications + +
+
+
+ 01 +

Hard Type Floor (max(22px, ...))

+
+

+ Replaces pure dynamic downscaling with an enforced floor. On mobile screens, lyric lines never scale below 22px (or 26px for near, 30px for active sung lines), guaranteeing stage visibility from 1.5–3 meters. +

+
.service-lyrics .sl-line { font-size: max(22px, calc(var(--fit, 40px) * 0.48)); }
+
+ +
+
+ 02 +

Two-Line Wrap Instead of Shrinking

+
+

+ When a hymn line contains long theological poetry, text-wrap: balance and overflow-wrap: break-word wrap it gracefully across 2 lines with tight line-height: 1.25 rather than crushing the font into micro-text. +

+
overflow-wrap: break-word; text-wrap: balance; line-height: 1.25;
+
+ +
+
+ 03 +

Generous Breathing Gap (clamp(14px, 3.2vh, 40px))

+
+

+ Replaces tight margins with a responsive CSS clamp. On smaller iPhone screens it ensures at least 14–26px between verse lines; on tall iPads and sanctuary projectors it expands cleanly up to 40px without crowding. +

+
.service-lyrics .sl-list { gap: clamp(14px, 3.2vh, 40px); }
+
+ +
+
+ 04 +

Accent Pill & Radiant Glow Elevation

+
+

+ The active sung line commands immediate focal attention through an 18% accent tint (color-mix) and a 34px radial glow box-shadow, distinguishing it unmistakably from adjacent lines. +

+
background-color: color-mix(in srgb, var(--accent) 18%, transparent);
+
+
+
+
+ + + + diff --git a/frontend/app.js b/frontend/app.js index d7c69f3..028beb1 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -2347,6 +2347,9 @@ function updateNowPlayingActions() { btn.title = 'Save this video for offline playback'; } } +// Smallest font (px) the sung line may be fitted to in service mode; longer lines wrap instead. +const SERVICE_LYRIC_MIN_PX = 30; + // ============================================================================ // Shared: size each lyric row (.sl-line) to the largest font that fits ONE row // ============================================================================ @@ -2355,13 +2358,12 @@ function updateNowPlayingActions() { // optical-size axis, so glyphs get relatively WIDER as the size drops and a // single measurement at 100px over-fits on small screens. Sets --fit per row; // with `uniform` every row gets the smallest fit, so all lines share one size. -function fitLyricLines(list, { maxShare = 0.17, maxPx = 160, uniform = false } = {}) { +function fitLyricLines(list, { maxShare = 0.17, maxPx = 160, minPx = 18, uniform = false } = {}) { if (!list) return; const rows = [...list.querySelectorAll('.sl-line')]; if (!rows.length || !list.clientWidth) return; const width = list.clientWidth * 0.92 * 0.97; // 4% side padding + slack const cap = Math.max(30, Math.min(list.clientHeight * maxShare, maxPx)); - const minPx = 18; const clamp = (px) => Math.max(minPx, Math.min(cap, px)); const probe = document.createElement('div'); probe.className = 'sl-line'; @@ -3100,7 +3102,7 @@ const Notes = (() => { const list = $('serviceLyricsList'); const plain = plainLyrics(); list.classList.toggle('plain', plain); - fitLyricLines(list, { uniform: plain }); + fitLyricLines(list, { uniform: plain, minPx: SERVICE_LYRIC_MIN_PX }); } function renderServiceButtons() { diff --git a/frontend/styles.css b/frontend/styles.css index 38ccdcf..f40b894 100755 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -3815,6 +3815,14 @@ body.remote-open { overflow: hidden; } .sl-line.untimed { cursor: default; } /* Plain lyrics (no timings): one shared --fit, every line full size. */ .sl-list.plain .sl-line { font-size: var(--fit, 40px); opacity: 0.92; color: var(--text); } +/* Service mode only: a floor under every lyric size (long lines wrap rather + than shrink) and breathing room between verses. Keep the floor in step with + SERVICE_LYRIC_MIN_PX in app.js. */ +.service-lyrics .sl-list { display: flex; flex-direction: column; gap: clamp(14px, 3.2vh, 40px); } +.service-lyrics .sl-line { font-size: max(22px, calc(var(--fit, 40px) * 0.48)); } +.service-lyrics .sl-line.near { font-size: max(26px, calc(var(--fit, 40px) * 0.6)); } +.service-lyrics .sl-line.active { font-size: max(30px, var(--fit, 40px)); } +.service-lyrics .sl-list.plain .sl-line { font-size: max(30px, var(--fit, 40px)); } .sl-empty { display: flex; flex-direction: column; gap: 10px; align-items: center; font-size: clamp(22px, 4vw, 40px); font-weight: 700; color: var(--text-2);