Tighten bottom UI, fix ch-bug/ticker/hamburger, reduce gradients
Layout: - Move NOW PLAYING ticker into #np-strip above scrubber; #bb is controls-only at 46px - --bot-h: 76px → 46px; #tc repositioned to clear new ticker strip - #np-strip added to idle slide-out animation Bug fixes: - Channel bug (#ch-bug) now hides during title card display, restores after - Reset A.npTitle/A.npArtist in loadCh() so ticker always updates on channel change - Hamburger (☰) and C key always open to MY LIST tab Visual: - .gt gradient 140px → 72px, .gb gradient 220px → 140px (less intrusive) Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
+19
-17
@@ -17,7 +17,7 @@
|
|||||||
--accent:#ff2200;--accent2:#00d4ff;--text:#f0f0ff;--dim:#6668a0;
|
--accent:#ff2200;--accent2:#00d4ff;--text:#f0f0ff;--dim:#6668a0;
|
||||||
--font-d:'Bebas Neue',Impact,'Arial Black',sans-serif;
|
--font-d:'Bebas Neue',Impact,'Arial Black',sans-serif;
|
||||||
--font-b:'Rajdhani',sans-serif;
|
--font-b:'Rajdhani',sans-serif;
|
||||||
--top-h:52px;--bot-h:76px;
|
--top-h:52px;--bot-h:46px;
|
||||||
}
|
}
|
||||||
html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-family:var(--font-b);color:var(--text);user-select:none;-webkit-tap-highlight-color:transparent}
|
html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-family:var(--font-b);color:var(--text);user-select:none;-webkit-tap-highlight-color:transparent}
|
||||||
|
|
||||||
@@ -61,8 +61,8 @@ html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-famil
|
|||||||
#pw iframe{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border:none;pointer-events:none}
|
#pw iframe{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border:none;pointer-events:none}
|
||||||
|
|
||||||
/* Overlays */
|
/* Overlays */
|
||||||
.gt{position:absolute;top:0;left:0;right:0;height:140px;background:linear-gradient(180deg,rgba(6,6,15,.92) 0%,transparent 100%);z-index:2;pointer-events:none}
|
.gt{position:absolute;top:0;left:0;right:0;height:72px;background:linear-gradient(180deg,rgba(6,6,15,.92) 0%,transparent 100%);z-index:2;pointer-events:none}
|
||||||
.gb{position:absolute;bottom:0;left:0;right:0;height:220px;background:linear-gradient(0deg,rgba(6,6,15,1) 0%,rgba(6,6,15,.92) 35%,rgba(6,6,15,.55) 65%,transparent 100%);z-index:2;pointer-events:none}
|
.gb{position:absolute;bottom:0;left:0;right:0;height:140px;background:linear-gradient(0deg,rgba(6,6,15,1) 0%,rgba(6,6,15,.85) 30%,rgba(6,6,15,.4) 65%,transparent 100%);z-index:2;pointer-events:none}
|
||||||
.gr{position:absolute;top:0;right:0;bottom:0;width:220px;background:linear-gradient(270deg,rgba(6,6,15,.85) 0%,rgba(6,6,15,.4) 50%,transparent 100%);z-index:2;pointer-events:none}
|
.gr{position:absolute;top:0;right:0;bottom:0;width:220px;background:linear-gradient(270deg,rgba(6,6,15,.85) 0%,rgba(6,6,15,.4) 50%,transparent 100%);z-index:2;pointer-events:none}
|
||||||
.gl{position:absolute;top:0;left:0;bottom:0;width:180px;background:linear-gradient(90deg,rgba(6,6,15,.85) 0%,rgba(6,6,15,.4) 50%,transparent 100%);z-index:2;pointer-events:none}
|
.gl{position:absolute;top:0;left:0;bottom:0;width:180px;background:linear-gradient(90deg,rgba(6,6,15,.85) 0%,rgba(6,6,15,.4) 50%,transparent 100%);z-index:2;pointer-events:none}
|
||||||
#scanlines{position:absolute;inset:0;z-index:3;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 3px,rgba(0,0,0,.055) 3px,rgba(0,0,0,.055) 4px);opacity:.5}
|
#scanlines{position:absolute;inset:0;z-index:3;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 3px,rgba(0,0,0,.055) 3px,rgba(0,0,0,.055) 4px);opacity:.5}
|
||||||
@@ -119,9 +119,8 @@ html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-famil
|
|||||||
#pb-thumb{position:absolute;right:-5px;top:-3px;width:10px;height:10px;background:#fff;border-radius:50%;opacity:0;transition:opacity .15s;pointer-events:none}
|
#pb-thumb{position:absolute;right:-5px;top:-3px;width:10px;height:10px;background:#fff;border-radius:50%;opacity:0;transition:opacity .15s;pointer-events:none}
|
||||||
|
|
||||||
/* Bottom bar */
|
/* Bottom bar */
|
||||||
#bb{position:absolute;bottom:0;left:0;right:0;height:var(--bot-h);z-index:5;display:flex;flex-direction:column;justify-content:center;align-items:stretch;padding:5px 14px;gap:2px}
|
#np-strip{position:absolute;bottom:calc(var(--bot-h) + 3px);left:0;right:0;height:26px;z-index:5;display:flex;align-items:center;padding:0 14px;gap:8px}
|
||||||
.bb-top{display:flex;align-items:center;gap:8px;}
|
#bb{position:absolute;bottom:0;left:0;right:0;height:var(--bot-h);z-index:5;display:flex;align-items:center;justify-content:center;padding:0 14px}
|
||||||
.bb-bot{display:flex;justify-content:center;align-items:center}
|
|
||||||
.np-lbl{font-family:var(--font-d);font-size:12px;letter-spacing:2.5px;color:var(--accent);flex-shrink:0;display:flex;align-items:center;gap:5px;white-space:nowrap}
|
.np-lbl{font-family:var(--font-d);font-size:12px;letter-spacing:2.5px;color:var(--accent);flex-shrink:0;display:flex;align-items:center;gap:5px;white-space:nowrap}
|
||||||
.np-lbl-dot{width:5px;height:5px;background:var(--accent);border-radius:50%;animation:dot-p 1s ease-in-out infinite}
|
.np-lbl-dot{width:5px;height:5px;background:var(--accent);border-radius:50%;animation:dot-p 1s ease-in-out infinite}
|
||||||
.np-wrap{flex:1;overflow:hidden;height:26px;position:relative}
|
.np-wrap{flex:1;overflow:hidden;height:26px;position:relative}
|
||||||
@@ -231,23 +230,23 @@ html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-famil
|
|||||||
}
|
}
|
||||||
@media(max-width:420px){
|
@media(max-width:420px){
|
||||||
.c-btn{width:30px;height:30px;font-size:13px}
|
.c-btn{width:30px;height:30px;font-size:13px}
|
||||||
#bb{gap:7px;padding:0 10px}
|
#np-strip{padding:0 10px}
|
||||||
.np-lbl{display:none}
|
.np-lbl{display:none}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Title card (lower-third) ── */
|
/* ── Title card (lower-third) ── */
|
||||||
#tc{position:absolute;bottom:calc(var(--bot-h) + 16px);left:0;z-index:7;padding:0 24px 0 20px;pointer-events:none;opacity:0;transform:translateY(14px);transition:opacity .45s ease,transform .45s ease;max-width:75vw}
|
#tc{position:absolute;bottom:calc(var(--bot-h) + 45px);left:0;z-index:7;padding:0 24px 0 20px;pointer-events:none;opacity:0;transform:translateY(14px);transition:opacity .45s ease,transform .45s ease;max-width:75vw}
|
||||||
#tc.show{opacity:1;transform:translateY(0)}
|
#tc.show{opacity:1;transform:translateY(0)}
|
||||||
#tc.hide{opacity:0;transform:translateY(6px);transition:opacity .6s ease,transform .6s ease}
|
#tc.hide{opacity:0;transform:translateY(6px);transition:opacity .6s ease,transform .6s ease}
|
||||||
.tc-bar{position:absolute;left:0;top:4px;bottom:4px;width:4px;background:var(--accent)}
|
.tc-bar{position:absolute;left:0;top:4px;bottom:4px;width:4px;background:var(--accent)}
|
||||||
.tc-artist{font-family:var(--font-d);font-size:clamp(13px,1.8vw,18px);letter-spacing:3px;color:var(--accent2);text-transform:uppercase;line-height:1.2;margin-bottom:3px;text-shadow:0 1px 12px rgba(0,0,0,.9)}
|
.tc-artist{font-family:var(--font-d);font-size:clamp(13px,1.8vw,18px);letter-spacing:3px;color:var(--accent2);text-transform:uppercase;line-height:1.2;margin-bottom:3px;text-shadow:0 1px 12px rgba(0,0,0,.9)}
|
||||||
.tc-title{font-family:var(--font-d);font-size:clamp(26px,4.5vw,52px);letter-spacing:1px;color:#fff;line-height:1.05;text-shadow:0 2px 24px rgba(0,0,0,.95)}
|
.tc-title{font-family:var(--font-d);font-size:clamp(26px,4.5vw,52px);letter-spacing:1px;color:#fff;line-height:1.05;text-shadow:0 2px 24px rgba(0,0,0,.95)}
|
||||||
@media(max-width:600px){
|
@media(max-width:600px){
|
||||||
#tc{max-width:90vw;bottom:calc(var(--bot-h) + 10px)}
|
#tc{max-width:90vw;bottom:calc(var(--bot-h) + 39px)}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Idle / broadcast mode ── */
|
/* ── Idle / broadcast mode ── */
|
||||||
#tb,#bb,#pb-wrap{
|
#tb,#bb,#pb-wrap,#np-strip{
|
||||||
will-change:transform,opacity;
|
will-change:transform,opacity;
|
||||||
transition:transform .5s cubic-bezier(.4,0,.15,1), opacity .5s ease;
|
transition:transform .5s cubic-bezier(.4,0,.15,1), opacity .5s ease;
|
||||||
}
|
}
|
||||||
@@ -257,6 +256,7 @@ body.idle{cursor:none}
|
|||||||
body.idle #tb{transform:translateY(-120%) scaleY(0.5);transform-origin:top center;opacity:0}
|
body.idle #tb{transform:translateY(-120%) scaleY(0.5);transform-origin:top center;opacity:0}
|
||||||
body.idle #bb{transform:translateY(120%) scaleY(0.5);transform-origin:bottom center;opacity:0}
|
body.idle #bb{transform:translateY(120%) scaleY(0.5);transform-origin:bottom center;opacity:0}
|
||||||
body.idle #pb-wrap{opacity:0}
|
body.idle #pb-wrap{opacity:0}
|
||||||
|
body.idle #np-strip{transform:translateY(120%) scaleY(0.5);transform-origin:bottom center;opacity:0}
|
||||||
body.idle #scanlines{opacity:.68}
|
body.idle #scanlines{opacity:.68}
|
||||||
body.idle #ch-bug{opacity:1}
|
body.idle #ch-bug{opacity:1}
|
||||||
body.idle #tc{bottom:20px}
|
body.idle #tc{bottom:20px}
|
||||||
@@ -370,8 +370,7 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
|||||||
<div id="pb"><div id="pb-thumb"></div></div>
|
<div id="pb"><div id="pb-thumb"></div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="bb">
|
<div id="np-strip">
|
||||||
<div class="bb-top">
|
|
||||||
<div class="np-lbl"><span class="np-lbl-dot"></span><span>NOW PLAYING</span></div>
|
<div class="np-lbl"><span class="np-lbl-dot"></span><span>NOW PLAYING</span></div>
|
||||||
<div class="np-wrap">
|
<div class="np-wrap">
|
||||||
<div id="np-ticker">
|
<div id="np-ticker">
|
||||||
@@ -379,7 +378,8 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bb-bot">
|
|
||||||
|
<div id="bb">
|
||||||
<div class="ctrls">
|
<div class="ctrls">
|
||||||
<button class="c-btn" id="b-prev" title="Previous (←)">⏪</button>
|
<button class="c-btn" id="b-prev" title="Previous (←)">⏪</button>
|
||||||
<button class="c-btn" id="b-play" title="Play / Pause (Space)">▶</button>
|
<button class="c-btn" id="b-play" title="Play / Pause (Space)">▶</button>
|
||||||
@@ -388,7 +388,6 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
|||||||
<button class="c-btn" id="b-sb" title="Channels (C)">☰</button>
|
<button class="c-btn" id="b-sb" title="Channels (C)">☰</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="lo"><div class="ldr"><div class="lb"></div><div class="lb"></div><div class="lb"></div><div class="lb"></div></div></div>
|
<div id="lo"><div class="ldr"><div class="lb"></div><div class="lb"></div><div class="lb"></div><div class="lb"></div></div></div>
|
||||||
<div id="toast"></div>
|
<div id="toast"></div>
|
||||||
@@ -531,6 +530,7 @@ function loadCh(i){
|
|||||||
A.player.stopVideo();
|
A.player.stopVideo();
|
||||||
const startIdx=A.shuffled?Math.floor(Math.random()*30):0;
|
const startIdx=A.shuffled?Math.floor(Math.random()*30):0;
|
||||||
A.player.loadPlaylist({list:ch.pid,listType:'playlist',index:startIdx});
|
A.player.loadPlaylist({list:ch.pid,listType:'playlist',index:startIdx});
|
||||||
|
A.npTitle=''; A.npArtist='';
|
||||||
setTicker('',ch.title);
|
setTicker('',ch.title);
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
try{
|
try{
|
||||||
@@ -572,16 +572,18 @@ function cleanArtist(s){
|
|||||||
|
|
||||||
function showTitleCard(artist, title){
|
function showTitleCard(artist, title){
|
||||||
if(!title) return;
|
if(!title) return;
|
||||||
const card=qs('#tc');
|
const card=qs('#tc'), bug=qs('#ch-bug');
|
||||||
qs('#tc-artist').textContent = artist||'';
|
qs('#tc-artist').textContent = artist||'';
|
||||||
qs('#tc-title').textContent = title||'';
|
qs('#tc-title').textContent = title||'';
|
||||||
card.classList.remove('hide');
|
card.classList.remove('hide');
|
||||||
card.classList.add('show');
|
card.classList.add('show');
|
||||||
|
if(bug) bug.style.opacity='0';
|
||||||
clearTimeout(A.tcTimer);
|
clearTimeout(A.tcTimer);
|
||||||
// hold for 2.8s then fade out
|
// hold for 2.8s then fade out
|
||||||
A.tcTimer = setTimeout(()=>{
|
A.tcTimer = setTimeout(()=>{
|
||||||
card.classList.remove('show');
|
card.classList.remove('show');
|
||||||
card.classList.add('hide');
|
card.classList.add('hide');
|
||||||
|
if(bug) bug.style.opacity='';
|
||||||
}, 2800);
|
}, 2800);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -981,7 +983,7 @@ function wireControls(){
|
|||||||
localStorage.setItem('vf_shuffle', A.shuffled);
|
localStorage.setItem('vf_shuffle', A.shuffled);
|
||||||
toast(A.shuffled?'\u21cc Shuffle ON':'Shuffle OFF');
|
toast(A.shuffled?'\u21cc Shuffle ON':'Shuffle OFF');
|
||||||
};
|
};
|
||||||
qs('#b-sb').onclick=openSB;
|
qs('#b-sb').onclick=()=>{ openSB(); renderTab('channels'); };
|
||||||
qs('#b-shuf').classList.toggle('act',A.shuffled); // reflect default shuffle state
|
qs('#b-shuf').classList.toggle('act',A.shuffled); // reflect default shuffle state
|
||||||
qs('#sb-close').onclick=closeSB;
|
qs('#sb-close').onclick=closeSB;
|
||||||
qs('#ts').onclick=()=>{ try{A.player?.playVideo?.();}catch(e){} hideTap(); };
|
qs('#ts').onclick=()=>{ try{A.player?.playVideo?.();}catch(e){} hideTap(); };
|
||||||
@@ -1044,7 +1046,7 @@ function wireControls(){
|
|||||||
try{A.player?.setShuffle?.(A.shuffled);}catch(err){}
|
try{A.player?.setShuffle?.(A.shuffled);}catch(err){}
|
||||||
localStorage.setItem('vf_shuffle', A.shuffled);
|
localStorage.setItem('vf_shuffle', A.shuffled);
|
||||||
toast(A.shuffled?'⇌ Shuffle ON':'Shuffle OFF');
|
toast(A.shuffled?'⇌ Shuffle ON':'Shuffle OFF');
|
||||||
} else if(e.code==='KeyC'){ openSB();
|
} else if(e.code==='KeyC'){ openSB(); renderTab('channels');
|
||||||
} else if(e.code==='KeyP'){ window.opener ? window.close() : popOut();
|
} else if(e.code==='KeyP'){ window.opener ? window.close() : popOut();
|
||||||
} else if(e.code==='KeyF'){
|
} else if(e.code==='KeyF'){
|
||||||
if(!document.fullscreenElement) document.documentElement.requestFullscreen?.().catch(()=>{});
|
if(!document.fullscreenElement) document.documentElement.requestFullscreen?.().catch(()=>{});
|
||||||
|
|||||||
Reference in New Issue
Block a user