diff --git a/app.js b/app.js index e5ea2f0..d28c358 100644 --- a/app.js +++ b/app.js @@ -2030,3 +2030,36 @@ function showTimmySpeech(text) { timmySpeechSprite = sprite; timmySpeechState = { startTime: clock.getElapsedTime(), sprite }; } + +// === BITCOIN BLOCK HEIGHT === +// Polls blockstream.info every 60 s for the current tip block height. +// Shows a flash animation when the block number increments. + +const blockHeightDisplay = document.getElementById('block-height-display'); +const blockHeightValue = document.getElementById('block-height-value'); +let lastKnownBlockHeight = null; + +async function fetchBlockHeight() { + try { + const res = await fetch('https://blockstream.info/api/blocks/tip/height'); + if (!res.ok) return; + const height = parseInt(await res.text(), 10); + if (isNaN(height)) return; + + if (lastKnownBlockHeight !== null && height !== lastKnownBlockHeight) { + // New block — trigger flash + blockHeightDisplay.classList.remove('fresh'); + // Force reflow so animation restarts + void blockHeightDisplay.offsetWidth; + blockHeightDisplay.classList.add('fresh'); + } + + lastKnownBlockHeight = height; + blockHeightValue.textContent = height.toLocaleString(); + } catch (_) { + // Network unavailable — keep last known value + } +} + +fetchBlockHeight(); +setInterval(fetchBlockHeight, 60000); diff --git a/index.html b/index.html index a5715f5..93e9dca 100644 --- a/index.html +++ b/index.html @@ -51,6 +51,11 @@
⚡ SOVEREIGNTY ⚡
+
+ ⛏ BLOCK + +
+
ZOOMED: Object [Esc] or double-click to exit diff --git a/style.css b/style.css index 7912ae2..4ac8b3d 100644 --- a/style.css +++ b/style.css @@ -234,6 +234,42 @@ body.photo-mode #overview-indicator { 100% { opacity: 0; transform: translate(-50%, -50%) scale(1); } } +/* === BITCOIN BLOCK HEIGHT === */ +#block-height-display { + position: fixed; + bottom: 12px; + right: 12px; + z-index: 20; + font-family: var(--font-body); + font-size: 11px; + letter-spacing: 0.15em; + color: var(--color-primary); + background: rgba(0, 0, 8, 0.7); + border: 1px solid var(--color-secondary); + padding: 4px 10px; + pointer-events: none; + white-space: nowrap; +} + +.block-height-label { + color: var(--color-text-muted); + margin-right: 6px; + font-size: 10px; +} + +#block-height-value { + color: var(--color-primary); +} + +#block-height-display.fresh #block-height-value { + animation: block-flash 0.6s ease-out; +} + +@keyframes block-flash { + 0% { color: #ffffff; text-shadow: 0 0 8px #4488ff; } + 100% { color: var(--color-primary); text-shadow: none; } +} + /* === CRT / CYBERPUNK OVERLAY === */ .crt-overlay { position: fixed;