From f5e1949c918e24748bf200bc66210836c34b71e1 Mon Sep 17 00:00:00 2001 From: vini Date: Sun, 19 Jul 2026 21:06:36 -0300 Subject: [PATCH] Improve overlay readability and swap lyrics/album layout Now-playing ticker gets a dark blurred pill, lyrics get a fading dark veil plus dark text shadows so both stay readable over the Milky Way. Lyrics move back to the left, album art to the right. PLANET_SPECS no longer hard-crashes the whole script if Astronomy Engine fails to load, and CLAUDE.md catches up with the planetarium features. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_015HtPHsTnDcLVSCiF5FGHZj --- CLAUDE.md | 15 +++++++++++++-- plugin/contents/ui/dancer.html | 33 ++++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 48d7e47..7bd1631 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,8 +34,14 @@ plugin/ main.qml # Plasma WallpaperItem — hosts everything dancer.html # Self-contained animation (HTML + CSS + JS) starcatalog.js # Generated star data (Yale BSC) — see tools/build_catalog.py + constellations.js # Generated zodiac lines/anchors — see tools/build_constellations.py + constellation-art/ # 12 zodiac PNGs (black background → alpha at load) + milkyway.jpg # Gaia all-sky photo, plate carrée — see tools/build_skymap.py + astronomy.browser.min.js # Astronomy Engine (MIT) — Moon/planet ephemerides tools/ build_catalog.py # Regenerates starcatalog.js from the Yale Bright Star Catalog + build_constellations.py # Regenerates constellations.js (Stellarium Modern + d3-celestial) + build_skymap.py # Reprojects ESA Gaia all-sky map (Hammer → plate carrée) ``` ### main.qml — the Plasma host @@ -50,13 +56,18 @@ Pure HTML/CSS/JS, no external dependencies. All visuals are self-contained: | Layer | Technique | |---|---| -| Realistic sky (stars + Milky Way) | ``; real-time alt-az projection of `starcatalog.js` (2,887 Yale BSC stars) + seeded procedural Milky Way for the configured lat/long (default Toledo-PR). Static layer pre-rendered offscreen, bright stars twinkle per frame; reprojects every 30 s. Debug: `window.__skyTimeOffset` (ms) fast-forwards the sky | +| Realistic sky (stars) | ``; real-time alt-az projection of `starcatalog.js` (8,404 Yale BSC stars, V ≤ 6.5) for the configured lat/long (default Toledo-PR). Static layer pre-rendered offscreen with triple-buffer + 1.4 s crossfade between reprojections (every 30 s; 4 s during timelapse/camera rotation); bright stars twinkle per frame. Debug: `window.__skyTimeOffset` (ms) fast-forwards the sky | +| Milky Way | Per-pixel sampling of `milkyway.jpg` (Gaia photo, full res): `buildMwGrid` caches viewport unit vectors + extinction/glare, `renderMilkyWay` applies only the sidereal rotation (camera azimuth folded into the equatorial→galactic matrix) and stylized "development" (deep blacks, saturation, cool shadows). Decoded texture stays resident (~75 MB) | +| Moon & planets | Astronomy Engine topocentric ephemerides: Moon with real phase texture + bright-limb angle, 7 planets with magnitude-scaled dots (labels only in constellation mode) | +| Zodiac constellations | Stellarium Modern lines + anchored PNG art (similarity transform, no shear); toggled via `/tmp` file or `C` key | | Nebula blobs, grid floor, horizon | CSS animations | | DANCEBOT-9000 robot | Pure CSS (divs + `@keyframes`) | | Chest EQ bars & VU meter | JS-driven `requestAnimationFrame` | -| Music ticker | DOM text set by `updateMusic(artist, title)` (called from QML) | +| 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. + **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. **Dance styles** (cycle order): `bounce → wave → shuffle → moonwalk → spin`. CSS selectors like `[data-dance="spin"] .robot { ... }` override the default animations via `!important`. diff --git a/plugin/contents/ui/dancer.html b/plugin/contents/ui/dancer.html index 4c16932..073c4a5 100644 --- a/plugin/contents/ui/dancer.html +++ b/plugin/contents/ui/dancer.html @@ -164,7 +164,7 @@ body.balada .nebula::after { opacity: 1; } .album-art { position: absolute; top: 4%; - left: 2%; + right: 2%; width: 330px; height: 330px; border-radius: 6px; @@ -194,6 +194,12 @@ body.balada .nebula::after { opacity: 1; } overflow: hidden; opacity: 0; transition: opacity 0.8s, top 0.8s ease; + /* legibilidade sobre a Via Láctea: pílula escura + desfoque do fundo */ + padding: 5px 16px; + border-radius: 999px; + background: rgba(3, 8, 20, 0.55); + backdrop-filter: blur(6px); + border: 1px solid rgba(0, 200, 255, 0.14); } body.balada .music-ticker { /* acima do VU meter: bottom 5% + 70px barras + 10px gap */ @@ -219,7 +225,7 @@ body.balada .music-ticker { color: #ffffff; font-family: 'Courier New', monospace; font-size: clamp(11px, 1.2vw, 17px); - text-shadow: 0 0 8px rgba(0,200,255,0.7); + text-shadow: 0 1px 3px rgba(0,0,0,0.9), 0 0 8px rgba(0,200,255,0.7); white-space: nowrap; animation: musicScroll 18s linear infinite; } @@ -254,14 +260,20 @@ body.balada .music-ticker { ============================================================ */ .lyric-display { position: absolute; - right: 2%; + left: 2%; top: 4%; width: 38%; height: 150px; + padding: 0 14px; overflow: hidden; pointer-events: none; opacity: 0; transition: opacity 0.5s ease; + /* véu escuro atrás da letra p/ ler sobre a Via Láctea; a máscara vertical + também esmaece o véu, então as bordas continuam suaves */ + background: linear-gradient(to right, + rgba(3, 8, 20, 0.58) 0%, rgba(3, 8, 20, 0.38) 70%, transparent 100%); + border-radius: 10px; -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 15%, black 85%, transparent 100%); mask-image: linear-gradient(to bottom, transparent 0%, black 15%, black 85%, transparent 100%); } @@ -273,7 +285,7 @@ body.balada .music-ticker { .lyric-ctx { display: block; width: 100%; - text-align: right; /* letra ancorada à direita da tela */ + text-align: left; /* letra ancorada à esquerda da tela */ font-family: 'Courier New', monospace; letter-spacing: 0.02em; white-space: normal; @@ -1268,7 +1280,8 @@ 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 -const PLANET_SPECS = [ +/* Sem o Astronomy Engine o céu continua funcionando; só Lua/planetas somem */ +const PLANET_SPECS = typeof Astronomy === 'undefined' ? [] : [ [Astronomy.Body.Mercury, 'Mercúrio', [190, 188, 182]], [Astronomy.Body.Venus, 'Vênus', [255, 241, 204]], [Astronomy.Body.Mars, 'Marte', [238, 105, 70]], @@ -2430,12 +2443,14 @@ const ACTIVE_SHADOW = '0 0 6px var(--theme-color,rgba(0,200,255,0.5)),' + '0 2px 10px rgba(0,0,0,0.95)'; +const CTX_SHADOW = '0 1px 3px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.8)'; + const VERSE_STYLES = [ - { opacity:'0.2', fontSize:'clamp(11px,0.85vw,13px)', color:'#777', shadow:'' }, - { opacity:'0.48', fontSize:'clamp(13px,1.0vw,15px)', color:'#bbb', shadow:'' }, + { opacity:'0.2', fontSize:'clamp(11px,0.85vw,13px)', color:'#777', shadow: CTX_SHADOW }, + { opacity:'0.48', fontSize:'clamp(13px,1.0vw,15px)', color:'#bbb', shadow: CTX_SHADOW }, { opacity:'1', fontSize:'clamp(16px,1.3vw,18px)', color:'#fff', shadow: ACTIVE_SHADOW }, - { opacity:'0.48', fontSize:'clamp(13px,1.0vw,15px)', color:'#bbb', shadow:'' }, - { opacity:'0.2', fontSize:'clamp(11px,0.85vw,13px)', color:'#777', shadow:'' }, + { opacity:'0.48', fontSize:'clamp(13px,1.0vw,15px)', color:'#bbb', shadow: CTX_SHADOW }, + { opacity:'0.2', fontSize:'clamp(11px,0.85vw,13px)', color:'#777', shadow: CTX_SHADOW }, ]; let verseEls = [];