diff --git a/plugin/contents/ui/dancer.html b/plugin/contents/ui/dancer.html
index 169f8bc..d94cba8 100644
--- a/plugin/contents/ui/dancer.html
+++ b/plugin/contents/ui/dancer.html
@@ -1262,6 +1262,33 @@ const HORIZON_F = 0.585; // fração da altura da tela até o horizonte
const TWINKLE_MAG = 4.0; // até esta magnitude a estrela cintila; acima é estática
const DEG = Math.PI / 180;
window.__skyTimeOffset = 0; // debug: ms somados ao relógio p/ testar a rotação
+let skyTimeScale = 1;
+let skyClockRealMs = Date.now();
+let skyClockSimMs = skyClockRealMs;
+
+function skyNowMs() {
+ const realNow = Date.now();
+ return skyClockSimMs + (realNow - skyClockRealMs) * skyTimeScale +
+ window.__skyTimeOffset;
+}
+
+function setSkyTimeScale(scale) {
+ const realNow = Date.now();
+ scale = Number(scale);
+ if (!Number.isFinite(scale) || scale < 1) scale = 1;
+ if (scale === skyTimeScale) return;
+ if (scale === 1 || skyTimeScale === 1) {
+ /* Entrar e sair da prévia sempre parte do instante real, sem deixar o
+ wallpaper preso no futuro simulado. */
+ skyClockSimMs = realNow;
+ } else {
+ skyClockSimMs += (realNow - skyClockRealMs) * skyTimeScale;
+ }
+ skyClockRealMs = realNow;
+ skyTimeScale = scale;
+ lastProjMs = -Infinity;
+ projectSky();
+}
/* Tempo sideral local em graus (GMST + longitude leste) */
function localSiderealDeg(ms) {
@@ -1598,7 +1625,7 @@ function projectSky() {
}
const bctx = renderCanvas.getContext('2d');
bctx.clearRect(0, 0, W, bufferH);
- const lst = localSiderealDeg(Date.now() + window.__skyTimeOffset);
+ const lst = localSiderealDeg(skyNowMs());
const glareOn = !document.body.classList.contains('balada') &&
!document.body.classList.contains('chuva');
const nextTwinkList = [];
@@ -1684,7 +1711,8 @@ function resizeCanvas() {
}
function drawStars(ts) {
- if (ts - lastProjMs > 30000) { lastProjMs = ts; projectSky(); }
+ const projectionInterval = skyTimeScale > 1 ? 4000 : 30000;
+ if (ts - lastProjMs > projectionInterval) { lastProjMs = ts; projectSky(); }
ctx.clearRect(0, 0, canvas.width, canvas.height);
const transition = Math.max(0, Math.min(1,
(ts - skyTransitionStart) / SKY_TRANSITION_MS));
@@ -1714,6 +1742,22 @@ function drawStars(ts) {
window.addEventListener('resize', resizeCanvas);
+/* Prévia temporal controlada por toggle-sky-timelapse.sh. Em 360x, uma hora
+ sideral passa em dez segundos e o ciclo diário leva quatro minutos. */
+let skyTimeScaleFileVal = null;
+(function pollSkyTimeScaleFile() {
+ fetch('file:///tmp/skeledance-sky-timescale?t=' + Date.now())
+ .then(r => r.text())
+ .then(t => {
+ const v = t.trim();
+ if (v === skyTimeScaleFileVal) return;
+ skyTimeScaleFileVal = v;
+ setSkyTimeScale(v);
+ })
+ .catch(() => {})
+ .finally(() => setTimeout(pollSkyTimeScaleFile, 800));
+})();
+
/* ============================================================
FLOOR CANVAS — perspective grid with true vanishing point
============================================================ */
diff --git a/toggle-sky-timelapse.sh b/toggle-sky-timelapse.sh
new file mode 100755
index 0000000..a0f8aaa
--- /dev/null
+++ b/toggle-sky-timelapse.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+STATE_FILE=/tmp/skeledance-sky-timescale
+
+if [ "$(cat "$STATE_FILE" 2>/dev/null)" = "360" ]; then
+ printf '1\n' > "$STATE_FILE"
+ printf 'Céu em tempo real\n'
+else
+ printf '360\n' > "$STATE_FILE"
+ printf 'Céu acelerado 360x (1 hora a cada 10 segundos)\n'
+fi