diff --git a/CLAUDE.md b/CLAUDE.md
index e73a9a8..fafe055 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -66,7 +66,7 @@ Pure HTML/CSS/JS, no external dependencies. All visuals are self-contained:
| Music ticker / album art / karaoke lyrics | DOM text set by `updateMusic(artist, title)` (called from QML); lyrics left, album art right, ticker centered — all with dark veils/shadows for contrast over the Milky Way |
| Dance style cycling | `data-dance` attribute on `
`, toggled by JS every 8 s |
-**Runtime controls** (state files in `/tmp/skeledance-*`, polled every 800 ms by dancer.html; each has a root-level helper script): `toggle-balada.sh`, `toggle-chuva.sh` (mutually exclusive modes), `toggle-constellations.sh`, `preview-constellation.sh `, `set-camera-position.sh `, `toggle-camera-rotation.sh` (360° pan in 5 min), `toggle-sky-timelapse.sh` (360× time). `test-modes.sh` reloads the plugin and cycles modes.
+**Runtime controls** (state files in `/tmp/skeledance-*`, polled every 800 ms by dancer.html; each has a root-level helper script): `toggle-balada.sh`, `toggle-chuva.sh` (mutually exclusive modes), `toggle-constellations.sh`, `preview-constellation.sh `, `set-camera-position.sh `, `toggle-camera-rotation.sh` (360° pan in 5 min), `toggle-sky-timelapse.sh` (360× time), `set-sky-time.sh ` (jump the sky clock to a time of day; combines with the timelapse). `test-modes.sh` reloads the plugin and cycles modes.
**Tempo anchor**: everything is keyed to 120 BPM (`BEAT_MS = 500 ms`). CSS animation durations for the robot parts use multiples/fractions of 0.5 s, 1 s, or 2 s.
diff --git a/plugin/contents/ui/dancer.html b/plugin/contents/ui/dancer.html
index 558322c..d37dff4 100644
--- a/plugin/contents/ui/dancer.html
+++ b/plugin/contents/ui/dancer.html
@@ -1141,11 +1141,11 @@ body.chuva #sunChuvaFace { opacity: 1; transition: opacity 5s ease; }
opacity: 0;
transition: opacity 12s ease;
background: linear-gradient(to bottom,
- #7d4f94 0%,
- #b0619f 26%,
- #d183b3 44%,
- #e3a3b8 60%,
- #edc19e 66%,
+ #676074 0%,
+ #837a88 26%,
+ #a3939f 44%,
+ #bfaeb0 60%,
+ #d3c0ab 66%,
#5a7d4a 66.1%,
#3e5c35 82%,
#2a4126 100%);
@@ -1165,17 +1165,17 @@ body.dia:not(.balada):not(.chuva) #meteorLayer { opacity: 0; }
pointer-events: none;
opacity: 0;
transition: opacity 12s ease;
- filter: blur(42px);
+ filter: blur(26px);
background: radial-gradient(ellipse,
- rgba(238,205,228,0.60) 0%, rgba(216,168,205,0.30) 55%, transparent 75%);
+ rgba(232,226,232,0.95) 0%, rgba(198,186,200,0.55) 55%, transparent 78%);
will-change: transform, opacity;
}
-.cloud-a { width: 46vh; height: 11vh; top: 10%; left: 8%;
+.cloud-a { width: 62vh; height: 14vh; top: 10%; left: 8%;
animation: dayCloudDrift1 26s ease-in-out infinite alternate; }
-.cloud-b { width: 38vh; height: 9vh; top: 22%; right: 10%;
+.cloud-b { width: 52vh; height: 12vh; top: 22%; right: 8%;
animation: dayCloudDrift2 34s ease-in-out infinite alternate;
animation-delay: -12s; }
-.cloud-c { width: 30vh; height: 7vh; top: 36%; left: 32%;
+.cloud-c { width: 42vh; height: 9vh; top: 36%; left: 30%;
animation: dayCloudDrift3 22s ease-in-out infinite alternate;
animation-delay: -7s; }
@keyframes dayCloudDrift1 {
@@ -1190,7 +1190,7 @@ body.dia:not(.balada):not(.chuva) #meteorLayer { opacity: 0; }
from { transform: translateX(-1.5vw) scaleX(1.05); }
to { transform: translateX(2vw) scaleX(0.90); }
}
-body.dia:not(.balada):not(.chuva) .day-cloud { opacity: 0.8; }
+body.dia:not(.balada):not(.chuva) .day-cloud { opacity: 1; }
/* O sol vira sol de verdade: disco quente, sem listras retrô */
#sunDiaBg {
@@ -2260,6 +2260,26 @@ let skyTimeScaleFileVal = null;
.finally(() => setTimeout(pollSkyTimeScaleFile, 800));
})();
+/* Deslocamento do relógio do céu em horas, controlado por set-sky-time.sh
+ (pula p/ um horário de hoje; combina com o timelapse). */
+let skyOffsetFileVal = null;
+(function pollSkyOffsetFile() {
+ fetch('file:///tmp/skeledance-sky-offset?t=' + Date.now())
+ .then(r => r.text())
+ .then(t => {
+ const v = t.trim();
+ if (v === skyOffsetFileVal) return;
+ skyOffsetFileVal = v;
+ const hours = Number(v);
+ if (!Number.isFinite(hours)) return;
+ window.__skyTimeOffset = hours * 3600 * 1000;
+ lastProjMs = -Infinity;
+ projectSky();
+ })
+ .catch(() => {})
+ .finally(() => setTimeout(pollSkyOffsetFile, 800));
+})();
+
/* Posição fixa controlada por set-camera-position.sh. */
let cameraAzimuthFileVal = null;
(function pollCameraAzimuthFile() {
diff --git a/set-sky-time.sh b/set-sky-time.sh
new file mode 100755
index 0000000..f7f8c0a
--- /dev/null
+++ b/set-sky-time.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Pula o relógio do céu para hoje às HH:MM (ex.: ./set-sky-time.sh 06:15).
+# "off" (ou sem argumento) volta ao tempo real. Combina com o timelapse.
+
+STATE_FILE=/tmp/skeledance-sky-offset
+TARGET=${1:-off}
+
+if [ "$TARGET" = "off" ]; then
+ printf '0\n' > "$STATE_FILE"
+ printf 'Relógio do céu em tempo real\n'
+ exit 0
+fi
+
+target_epoch=$(date -d "today $TARGET" +%s) || exit 2
+now_epoch=$(date +%s)
+offset_h=$(awk "BEGIN { printf \"%.4f\", ($target_epoch - $now_epoch) / 3600 }")
+printf '%s\n' "$offset_h" > "$STATE_FILE"
+printf 'Relógio do céu em %s de hoje (offset %sh)\n' "$TARGET" "$offset_h"