diff --git a/background.html b/background.html
index fc571fe..34783c5 100644
--- a/background.html
+++ b/background.html
@@ -107,6 +107,22 @@
border: 1px solid var(--stone);
border-radius: 2px;
}
+ .debug-row-buttons {
+ flex-wrap: wrap;
+ gap: 4px;
+ }
+ .dbg-btn {
+ background: var(--panel);
+ color: var(--icon);
+ border: 1px solid var(--border);
+ border-radius: 2px;
+ padding: 2px 8px;
+ font-size: 11px;
+ font-family: inherit;
+ cursor: pointer;
+ }
+ .dbg-btn:hover { background: var(--raised); }
+ .dbg-btn.dbg-btn-toggle.on { background: var(--ember); color: var(--dark); }
.theme-table {
font-size: 0.9em;
margin-top: 4px;
@@ -339,7 +355,23 @@
Time: --
Day%: --
- Weather: --
+
+ Weather:
+ --
+
+
+
+
+
+
+
+
+
+
+
+
+
Theme: --
Speed: --
Transition: --
@@ -1414,6 +1446,57 @@ window.weatherThemes = {
}
}
+ // ---- Weather simulation -----------------------------------------
+ // Cycles through a list of weather states automatically. Useful
+ // for A/B testing the renderer against every theme without
+ // waiting on the open-meteo API.
+ var simWeathers = ['sunny', 'cloudy', 'stormy', 'night'];
+ var simIndex = 0;
+ var simTimer = null;
+ var __weatherSimActive = false;
+
+ function startWeatherSim(intervalMs) {
+ stopWeatherSim();
+ var step = intervalMs || (window.CONFIG && window.CONFIG.weatherSimInterval) || 30000;
+ simIndex = 0;
+ setWeatherTheme(simWeathers[simIndex]);
+ simTimer = setInterval(function() {
+ simIndex = (simIndex + 1) % simWeathers.length;
+ setWeatherTheme(simWeathers[simIndex]);
+ }, step);
+ __weatherSimActive = true;
+ }
+
+ function stopWeatherSim() {
+ if (simTimer) {
+ clearInterval(simTimer);
+ simTimer = null;
+ }
+ __weatherSimActive = false;
+ updateSimButton();
+ }
+
+ function updateSimButton() {
+ var btn = document.getElementById('dbg-btn-sim');
+ if (btn) {
+ btn.textContent = 'Auto-Cycle: ' + (__weatherSimActive ? 'on' : 'off');
+ btn.classList.toggle('on', __weatherSimActive);
+ }
+ }
+
+ function toggleWeatherSim() {
+ if (__weatherSimActive) {
+ stopWeatherSim();
+ } else {
+ startWeatherSim();
+ }
+ updateSimButton();
+ }
+
+ // Periodically refresh the toggle state in case another tab
+ // toggled it.
+ setInterval(updateSimButton, 1000);
+
function getEffectiveThemeColors() {
if (!targetThemeColors) return null;
@@ -1983,9 +2066,14 @@ window.weatherThemes = {
animate();
try { tick(); } catch (e) { console.error('Initial tick error:', e); }
- fetchWeather();
- setInterval(fetchWeather, 15 * 60 * 1000);
- tick();
+ // Weather source: real open-meteo API or local simulation
+ if (window.CONFIG && window.CONFIG.weatherSim) {
+ startWeatherSim(window.CONFIG.weatherSimInterval);
+ updateSimButton();
+ } else {
+ fetchWeather();
+ setInterval(fetchWeather, 15 * 60 * 1000);
+ }
} catch (e) {
window.__clouds2dError = e.message || String(e);
console.error('Background init error:', e);
diff --git a/config.js b/config.js
index 600f069..849823c 100644
--- a/config.js
+++ b/config.js
@@ -94,4 +94,12 @@ window.THEMES = {
'ash': 'ash.css',
'gruvbox': 'gruvbox.css',
'nord': 'nord.css'
+
+ // weatherSim - If true, ignore open-meteo and cycle through
+ // ['sunny', 'cloudy', 'stormy', 'night'] automatically
+ // every weatherSimInterval ms. Useful for testing
+ // every theme without waiting on the API.
+ // weatherSimInterval - Sim cycle period in ms (default 30000).
+ weatherSim: false,
+ weatherSimInterval: 30000,
};
\ No newline at end of file