Replace disconnected overlay with slim banner matching stale style

Same top-banner pattern as the stale indicator but with red accent
and 'Connection lost — retrying every 2s...' message. Page gets
subtle greyscale/dim instead of a blocking overlay.
This commit is contained in:
Jarvis 2026-02-21 11:15:18 +00:00
parent dd4787615d
commit 435b24bfb8

View file

@ -124,21 +124,17 @@ h1 { color: #fff; font-size: 1.5em; text-align: center; }
.zero-state h2 { color: #fff; font-size: 2em; }
.zero-state p { color: #888; font-size: 1.1em; max-width: 400px; line-height: 1.5; }
/* ===== DISCONNECTED OVERLAY ===== */
.disconnected-overlay {
position: fixed; inset: 0; background: rgba(0,0,0,0.7);
display: flex; align-items: center; justify-content: center;
z-index: 1000; backdrop-filter: blur(3px);
/* ===== DISCONNECTED BANNER ===== */
.disconnected-banner {
position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
background: rgba(40, 20, 20, 0.92); border-bottom: 1px solid #e74c3c;
padding: 8px 20px; text-align: center; font-size: 0.85em; color: #ccc;
display: none; backdrop-filter: blur(2px);
animation: stale-fade-in 0.3s ease-out;
}
.disconnected-overlay .message {
background: #16213e; border: 2px solid #e74c3c; border-radius: 12px;
padding: 40px; text-align: center; max-width: 400px;
}
.disconnected-overlay .icon { font-size: 3em; margin-bottom: 15px; }
.disconnected-overlay h3 { color: #e74c3c; margin-bottom: 10px; }
.disconnected-overlay p { color: #888; font-size: 0.9em; }
.disconnected-overlay .retry { color: #555; font-size: 0.8em; margin-top: 15px; }
body.greyed-out .container { filter: grayscale(80%) brightness(0.5); pointer-events: none; }
.disconnected-banner .icon { margin-right: 6px; }
.disconnected-banner .retry-text { color: #e74c3c; font-weight: 500; }
body.greyed-out .container { filter: grayscale(60%) brightness(0.6); }
/* ===== STALE STATE ===== */
.stale-banner {
@ -226,14 +222,10 @@ body.game-over .container { padding-top: 100px; }
</div>
</div>
<!-- Disconnected overlay -->
<div class="disconnected-overlay" id="disconnect-overlay" style="display:none">
<div class="message">
<div class="icon">📡</div>
<h3>Connection Lost</h3>
<p>Unable to reach the game server. The bridge may be down or the network is unreachable.</p>
<div class="retry" id="disconnect-retry">Retrying in <span id="retry-countdown">--</span>s...</div>
</div>
<!-- Disconnected banner -->
<div class="disconnected-banner" id="disconnect-banner">
<span class="icon">📡</span>
Connection lost — <span class="retry-text">retrying every 2s...</span>
</div>
<!-- Stale data banner -->
@ -283,8 +275,6 @@ let lastUpdate = '';
let currentView = 'loading'; // loading, zero, playing, gameover, disconnected
let debugMode = null; // null = live, or a forced state name
let consecutiveFailures = 0;
let retryCountdown = 0;
let retryTimer = null;
let gameOverShown = false; // only trigger confetti once per game
let confettiRunning = false;
let lastStateTimestamp = null; // ISO string from state.lastUpdated
@ -294,7 +284,7 @@ function showView(view) {
currentView = view;
document.getElementById('zero-state').style.display = view === 'zero' ? 'flex' : 'none';
document.getElementById('game-container').style.display = (view === 'playing' || view === 'gameover') ? 'flex' : 'none';
document.getElementById('disconnect-overlay').style.display = view === 'disconnected' ? 'flex' : 'none';
document.getElementById('disconnect-banner').style.display = view === 'disconnected' ? 'block' : 'none';
document.getElementById('game-over-banner').style.display = view === 'gameover' ? 'block' : 'none';
document.body.classList.toggle('greyed-out', view === 'disconnected');
document.body.classList.toggle('game-over', view === 'gameover');
@ -608,28 +598,14 @@ function hideStale() {
// ===== CONNECTION MONITORING =====
function showDisconnected() {
if (currentView === 'disconnected') return;
// Show the overlay on top of whatever was showing
document.getElementById('disconnect-overlay').style.display = 'flex';
document.getElementById('disconnect-banner').style.display = 'block';
document.body.classList.add('greyed-out');
startRetryCountdown();
}
function hideDisconnected() {
document.getElementById('disconnect-overlay').style.display = 'none';
document.getElementById('disconnect-banner').style.display = 'none';
document.body.classList.remove('greyed-out');
consecutiveFailures = 0;
if (retryTimer) { clearInterval(retryTimer); retryTimer = null; }
}
function startRetryCountdown() {
retryCountdown = 5;
document.getElementById('retry-countdown').textContent = retryCountdown;
if (retryTimer) clearInterval(retryTimer);
retryTimer = setInterval(() => {
retryCountdown--;
document.getElementById('retry-countdown').textContent = Math.max(0, retryCountdown);
}, 1000);
}
// ===== MAIN UPDATE LOOP =====