diff --git a/Auto-Image.js b/Auto-Image.js index cbbc75df..4bef3ac6 100644 --- a/Auto-Image.js +++ b/Auto-Image.js @@ -1,4 +1,14 @@ -// eslint-disable-next-line prettier/prettier +// ==UserScript== +// @name WPlaceBot +// @namespace http://tampermonkey.net/ +// @version 2025-08-08.3 +// @description Bot +// @author TH3C0D3R +// @match https://wplace.live/* +// @grant none +// @icon +// ==/UserScript== +localStorage.removeItem("lp"); ; (async () => { // CONFIGURATION CONSTANTS const CONFIG = { @@ -190,6 +200,27 @@ 'pixel-blink': true, }, }, + 'Acrylic': { + primary: '#00000080', + secondary: '#00000040', + accent: 'rgba(0,0,0,0.75)', + text: '#ffffff', + highlight: '#ffffff', + success: '#00e500', + error: '#e50000', + warning: '#e5e500', + fontFamily: "'Inter', 'Apple Color Emoji'", + borderRadius: '10px', + borderStyle: 'solid', + borderWidth: '0px', + boxShadow: 'none', + backdropFilter: 'blur(20px)', + animations: { + glow: false, + scanline: false, + 'pixel-blink': false, + }, + }, }, currentTheme: 'Classic Autobot', PAINT_UNAVAILABLE: true, @@ -222,6 +253,7 @@ document.documentElement.classList.remove( 'wplace-theme-classic', 'wplace-theme-classic-light', + 'wplace-theme-acrylic', 'wplace-theme-neon' ); @@ -230,6 +262,8 @@ themeClass = 'wplace-theme-neon'; } else if (CONFIG.currentTheme === 'Classic Light') { themeClass = 'wplace-theme-classic-light'; + } else if (CONFIG.currentTheme === 'Acrylic') { + themeClass = 'wplace-theme-acrylic'; } document.documentElement.classList.add(themeClass); @@ -239,7 +273,7 @@ const setVar = (k, v) => { try { root.style.setProperty(k, v); - } catch {} + } catch { } }; setVar('--wplace-primary', theme.primary); @@ -333,8 +367,7 @@ ) { loadedTranslations[language] = translations; console.log( - `📚 Loaded ${language} translations successfully from CDN (${ - Object.keys(translations).length + `📚 Loaded ${language} translations successfully from CDN (${Object.keys(translations).length } keys)` ); return translations; @@ -553,6 +586,7 @@ startPosition: null, selectingPosition: false, region: null, + experiments: null, minimized: false, lastPosition: { x: 0, y: 0 }, estimatedTime: 0, @@ -597,7 +631,9 @@ paintedMap: null, }; - let _updateResizePreview = () => {}; + state.experiments = localStorage.getItem("exp_wbot"); + + let _updateResizePreview = () => { }; let _resizeDialogCleanup = null; // --- OVERLAY UPDATE: Optimized OverlayManager class with performance improvements --- @@ -1189,7 +1225,9 @@ throw error; } } - + const randStr = (len, chars = 'abcdefghijklmnopqrstuvwxyz0123456789') => + [...Array(len)].map(() => chars[(crypto?.getRandomValues?.(new Uint32Array(1))[0] % chars.length) || Math.floor(Math.random() * chars.length)]).join('') + const fpStr32 = randStr(32); async function handleCaptchaFallback() { // Implementation for fallback token generation would go here // This is a placeholder for browser automation fallback @@ -1230,14 +1268,13 @@ if (payload.t) { // 📊 Debug log console.log( - `🔍✅ Turnstile Token Captured - Type: ${typeof payload.t}, Value: ${ - payload.t - ? typeof payload.t === 'string' - ? payload.t.length > 50 - ? payload.t.substring(0, 50) + '...' - : payload.t - : JSON.stringify(payload.t) - : 'null/undefined' + `🔍✅ Turnstile Token Captured - Type: ${typeof payload.t}, Value: ${payload.t + ? typeof payload.t === 'string' + ? payload.t.length > 50 + ? payload.t.substring(0, 50) + '...' + : payload.t + : JSON.stringify(payload.t) + : 'null/undefined' }, Length: ${payload.t?.length || 0}` ); window.postMessage({ source: 'turnstile-capture', token: payload.t }, '*'); @@ -1346,34 +1383,34 @@ // Debounced scroll-to-adjust handler for sliders createScrollToAdjust: (element, updateCallback, min, max, step = 1) => { let debounceTimer = null; - + const handleWheel = (e) => { // Only trigger when hovering over the slider if (e.target !== element) return; - + e.preventDefault(); e.stopPropagation(); - + // Clear existing debounce timer if (debounceTimer) { clearTimeout(debounceTimer); } - + // Debounce the adjustment to make it precise debounceTimer = setTimeout(() => { const currentValue = parseInt(element.value) || 0; const delta = e.deltaY > 0 ? -step : step; const newValue = Math.max(min, Math.min(max, currentValue + delta)); - + if (newValue !== currentValue) { element.value = newValue; updateCallback(newValue); } }, 50); // 50ms debounce for precise control }; - + element.addEventListener('wheel', handleWheel, { passive: false }); - + // Return cleanup function return () => { if (debounceTimer) clearTimeout(debounceTimer); @@ -1708,9 +1745,9 @@ return isTokenValid() ? { - sitekey: this._cachedSitekey, - token: turnstileToken, - } + sitekey: this._cachedSitekey, + token: turnstileToken, + } : { sitekey: this._cachedSitekey, token: null }; } @@ -1972,8 +2009,8 @@ const bdiff = pb - b; const dist = Math.sqrt( (((512 + rmean) * rdiff * rdiff) >> 8) + - 4 * gdiff * gdiff + - (((767 - rmean) * bdiff * bdiff) >> 8) + 4 * gdiff * gdiff + + (((767 - rmean) * bdiff * bdiff) >> 8) ); if (dist < menorDist) { menorDist = dist; @@ -2023,9 +2060,8 @@ }; } - const cacheKey = `${targetRgb[0]},${targetRgb[1]},${targetRgb[2]}|${state.colorMatchingAlgorithm}|${ - state.enableChromaPenalty ? 'c' : 'nc' - }|${state.chromaPenaltyWeight}|${exactMatch ? 'exact' : 'closest'}`; + const cacheKey = `${targetRgb[0]},${targetRgb[1]},${targetRgb[2]}|${state.colorMatchingAlgorithm}|${state.enableChromaPenalty ? 'c' : 'nc' + }|${state.chromaPenaltyWeight}|${exactMatch ? 'exact' : 'closest'}`; if (colorCache.has(cacheKey)) return colorCache.get(cacheKey); @@ -2075,8 +2111,8 @@ const bdiff = b - targetRgb[2]; const dist = Math.sqrt( (((512 + rmean) * rdiff * rdiff) >> 8) + - 4 * gdiff * gdiff + - (((767 - rmean) * bdiff * bdiff) >> 8) + 4 * gdiff * gdiff + + (((767 - rmean) * bdiff * bdiff) >> 8) ); if (dist < bestScore) { bestScore = dist; @@ -2224,8 +2260,7 @@ console.log('\n--- AVAILABLE COLORS ---'); availableColors.forEach((color, index) => { console.log( - `${ - index + 1 + `${index + 1 }. ID: ${color.id}, Name: "${color.name}", RGB: (${color.rgb[0]}, ${color.rgb[1]}, ${color.rgb[2]})` ); }); @@ -2235,8 +2270,7 @@ console.log('\n--- UNAVAILABLE COLORS ---'); unavailableColors.forEach((color, index) => { console.log( - `${ - index + 1 + `${index + 1 }. ID: ${color.id}, Name: "${color.name}", RGB: (${color.rgb[0]}, ${color.rgb[1]}, ${color.rgb[2]}) [LOCKED]` ); }); @@ -2517,11 +2551,11 @@ }, imageData: state.imageData ? { - width: state.imageData.width, - height: state.imageData.height, - pixels: Array.from(state.imageData.pixels), - totalPixels: state.imageData.totalPixels, - } + width: state.imageData.width, + height: state.imageData.height, + pixels: Array.from(state.imageData.pixels), + totalPixels: state.imageData.totalPixels, + } : null, paintedMapPacked: Utils.buildPaintedMapPacked(), }; @@ -2574,7 +2608,7 @@ if (migrated && migrated !== data) { try { localStorage.setItem('wplace-bot-progress', JSON.stringify(migrated)); - } catch {} + } catch { } } return migrated; } catch (error) { @@ -2826,10 +2860,12 @@ coords: [pixelX, pixelY], colors: [color], t: turnstileToken, + fp: fpStr32, }; + var token = await createWasmToken(regionX, regionY, payload); const res = await fetch(`https://backend.wplace.live/s0/pixel/${regionX}/${regionY}`, { method: 'POST', - headers: { 'Content-Type': 'text/plain;charset=UTF-8' }, + headers: { 'Content-Type': 'text/plain;charset=UTF-8', "x-pawtect-token": token }, credentials: 'include', body: JSON.stringify(payload), }); @@ -2986,9 +3022,9 @@ const colorCache = new Map(); // UI UPDATE FUNCTIONS (declared early to avoid reference errors) - let updateUI = () => {}; - let updateStats = (isManualRefresh) => {}; - let updateDataButtons = () => {}; + let updateUI = () => { }; + let updateStats = (isManualRefresh) => { }; + let updateDataButtons = () => { }; function updateActiveColorPalette() { state.activeColorPalette = []; @@ -3202,14 +3238,13 @@ // 📊 Debug log console.log( - `🔍 Token received - Type: ${typeof token}, Value: ${ - token - ? typeof token === 'string' - ? token.length > 50 - ? token.substring(0, 50) + '...' - : token - : JSON.stringify(token) - : 'null/undefined' + `🔍 Token received - Type: ${typeof token}, Value: ${token + ? typeof token === 'string' + ? token.length > 50 + ? token.substring(0, 50) + '...' + : token + : JSON.stringify(token) + : 'null/undefined' }, Length: ${token?.length || 0}` ); @@ -3349,6 +3384,37 @@ const existingResizeContainer = document.querySelector('.resize-container'); const existingResizeOverlay = document.querySelector('.resize-overlay'); + document.addEventListener("keydown", async function (event) { + if(state.running) return; + event.stopPropagation(); + switch (event.key) { + case "ArrowUp": + if (state?.startPosition?.y && state?.region?.y) { + state.startPosition.y--; + await overlayManager.setPosition(state.startPosition, state.region); + } + break; + case "ArrowDown": + if (state?.startPosition?.y && state?.region?.y) { + state.startPosition.y++; + await overlayManager.setPosition(state.startPosition, state.region); + } + break; + case "ArrowLeft": + if (state?.startPosition?.x && state?.region?.x) { + state.startPosition.x--; + await overlayManager.setPosition(state.startPosition, state.region); + } + break; + case "ArrowRight": + if (state?.startPosition?.x && state?.region?.x) { + state.startPosition.x++; + await overlayManager.setPosition(state.startPosition, state.region); + } + break; + } + }); + if (existingContainer) existingContainer.remove(); if (existingStats) existingStats.remove(); if (existingSettings) existingSettings.remove(); @@ -3433,8 +3499,8 @@
@@ -3504,8 +3570,8 @@ ${Utils.t('saveData')} @@ -3516,8 +3582,8 @@ ${Utils.t('saveToFile')} @@ -3539,8 +3605,8 @@
@@ -3580,19 +3646,17 @@ z-index: 99999; color: ${theme.text || 'white'}; font-family: ${theme.fontFamily || "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif"}; - box-shadow: ${ - theme.boxShadow || '0 20px 40px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1)' + box-shadow: ${theme.boxShadow || '0 20px 40px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1)' }; backdrop-filter: ${theme.backdropFilter || 'blur(10px)'}; overflow: hidden; animation: settings-slide-in 0.4s ease-out; - ${ - theme.animations?.glow - ? ` + ${theme.animations?.glow + ? ` box-shadow: ${theme.boxShadow || '0 20px 40px rgba(0,0,0,0.3)'}, 0 0 30px ${theme.highlight || theme.neon || '#00ffff'}; ` - : '' + : '' } `; @@ -3618,15 +3682,12 @@

Generator mode creates tokens automatically. Hybrid mode falls back to manual when generator fails. Manual mode only uses pixel placement. @@ -3646,9 +3707,8 @@

- Overlay Opacity + Overlay Opacity
${Math.round(state.overlayOpacity * 100)}%
@@ -3719,9 +3773,8 @@ ${Utils.t('paintWhitePixels')} -

+

${Utils.t('paintWhitePixelsDescription')}

@@ -3736,9 +3789,8 @@ ${Utils.t('paintTransparentPixels')} -

+

${Utils.t('paintTransparentPixelsDescription')}

@@ -3748,16 +3800,13 @@ @@ -3832,9 +3881,8 @@
@@ -3880,16 +3928,13 @@
@@ -3928,21 +3973,18 @@
${Utils.t('repeatEvery')} @@ -3951,11 +3993,11 @@
+ 'grantPermission' + )} + 'test' + )}
@@ -3969,13 +4011,12 @@
@@ -4151,18 +4192,18 @@
+ 'zoomOut' + )}"> + 'zoomIn' + )}"> + 'fitToView' + )}">${Utils.t('fit')} + 'actualSize' + )}">${Utils.t('hundred')} @@ -4241,12 +4282,10 @@
- +
@@ -4270,9 +4308,8 @@ Enable Dithering
Floyd–Steinberg error diffusion in preview and applied output
- +
${Utils.t( - 'pixels' - )}
+ 'pixels' + )}
${state.paintedPixels}/${state.totalPixels}
${Utils.t( - 'estimatedTime' - )}
+ 'estimatedTime' + )}
${Utils.formatTime(state.estimatedTime)}
`; @@ -5316,21 +5353,20 @@
--:--:--
- ${ - state.colorsChecked - ? ` + ${state.colorsChecked + ? `
${Utils.t( - 'availableColors', - { count: state.availableColors.length } - )}
+ 'availableColors', + { count: state.availableColors.length } + )}
${colorSwatchesHTML}
` - : '' - } + : '' + } `; // should be after statsArea.innerHTML = '...'. todo make full stats ui update partial @@ -6403,13 +6439,13 @@ _resizeDialogCleanup = () => { try { zoomSlider.replaceWith(zoomSlider.cloneNode(true)); - } catch {} + } catch { } try { if (zoomInBtn) zoomInBtn.replaceWith(zoomInBtn.cloneNode(true)); - } catch {} + } catch { } try { if (zoomOutBtn) zoomOutBtn.replaceWith(zoomOutBtn.cloneNode(true)); - } catch {} + } catch { } }; setTimeout(() => { if (typeof computeFitZoom === 'function') { @@ -6429,21 +6465,21 @@ if (typeof _resizeDialogCleanup === 'function') { _resizeDialogCleanup(); } - } catch {} + } catch { } resizeOverlay.style.display = 'none'; resizeContainer.style.display = 'none'; - _updateResizePreview = () => {}; + _updateResizePreview = () => { }; try { if (typeof cancelAnimationFrame === 'function' && _panRaf) { cancelAnimationFrame(_panRaf); } - } catch {} + } catch { } try { if (_previewTimer) { clearTimeout(_previewTimer); _previewTimer = null; } - } catch {} + } catch { } _maskImageData = null; _maskData = null; _dirty = null; @@ -6707,9 +6743,9 @@ Utils.showAlert( `${Utils.t('savedDataFound')}\n\n` + - `Saved: ${savedDate}\n` + - `Progress: ${savedData.state.paintedPixels}/${savedData.state.totalPixels} pixels (${progress}%)\n` + - `${Utils.t('clickLoadToContinue')}`, + `Saved: ${savedDate}\n` + + `Progress: ${savedData.state.paintedPixels}/${savedData.state.totalPixels} pixels (${progress}%)\n` + + `${Utils.t('clickLoadToContinue')}`, 'info' ); } @@ -6721,12 +6757,12 @@ const updateCooldown = (newValue) => { const threshold = Math.max(1, Math.min(state.maxCharges || 999, parseInt(newValue))); state.cooldownChargeThreshold = threshold; - + // Update both controls (value shows in input, label shows unit only) cooldownSlider.value = threshold; cooldownInput.value = threshold; cooldownValue.textContent = `${Utils.t('charges')}`; - + saveBotSettings(); NotificationManager.resetEdgeTracking(); // prevent spurious notify after threshold change }; @@ -7140,8 +7176,7 @@ ) { if (pixelBatch && pixelBatch.pixels.length > 0) { console.log( - `🌍 Sending region-change batch with ${pixelBatch.pixels.length} pixels (switching to region ${ - regionX + adderX + `🌍 Sending region-change batch with ${pixelBatch.pixels.length} pixels (switching to region ${regionX + adderX },${regionY + adderY})` ); const success = await flushPixelBatch(pixelBatch); @@ -7203,14 +7238,12 @@ continue; } console.debug( - `[COMPARE] Pixel at 📍 (${pixelX}, ${pixelY}) in region (${ - regionX + adderX + `[COMPARE] Pixel at 📍 (${pixelX}, ${pixelY}) in region (${regionX + adderX }, ${regionY + adderY})\n` + - ` ├── Current color: rgb(${tilePixelRGBA.slice(0, 3).join(', ')}) (id: ${mappedCanvasColor.id})\n` + - ` ├── Target color: rgb(${targetPixelInfo.r}, ${targetPixelInfo.g}, ${targetPixelInfo.b}) (id: ${targetMappedColorId})\n` + - ` └── Status: ${ - isMatch ? '✅ Already painted → SKIP' : '🔴 Needs paint → PAINT' - }\n` + ` ├── Current color: rgb(${tilePixelRGBA.slice(0, 3).join(', ')}) (id: ${mappedCanvasColor.id})\n` + + ` ├── Target color: rgb(${targetPixelInfo.r}, ${targetPixelInfo.g}, ${targetPixelInfo.b}) (id: ${targetMappedColorId})\n` + + ` └── Status: ${isMatch ? '✅ Already painted → SKIP' : '🔴 Needs paint → PAINT' + }\n` ); } } catch (e) { @@ -7310,12 +7343,11 @@ console.log(` Skipped - Already painted: ${skippedPixels.alreadyPainted}`); console.log(` Skipped - Color Unavailable: ${skippedPixels.colorUnavailable}`); console.log( - ` Total processed: ${ - state.paintedPixels + - skippedPixels.transparent + - skippedPixels.white + - skippedPixels.alreadyPainted + - skippedPixels.colorUnavailable + ` Total processed: ${state.paintedPixels + + skippedPixels.transparent + + skippedPixels.white + + skippedPixels.alreadyPainted + + skippedPixels.colorUnavailable }` ); @@ -7420,11 +7452,11 @@ } try { - const payload = { coords, colors, t: token }; - + const payload = { coords, colors, t: token, fp: fpStr32 }; + var wasmtoken = await createWasmToken(regionX, regionY, payload); const res = await fetch(`https://backend.wplace.live/s0/pixel/${regionX}/${regionY}`, { method: 'POST', - headers: { 'Content-Type': 'text/plain;charset=UTF-8' }, + headers: { 'Content-Type': 'text/plain;charset=UTF-8', "x-pawtect-token": wasmtoken }, credentials: 'include', body: JSON.stringify(payload), }); @@ -7433,7 +7465,7 @@ let data = null; try { data = await res.json(); - } catch (_) {} + } catch (_) { } console.error('❌ 403 Forbidden. Turnstile token might be invalid or expired.'); // Try to generate a new token and retry once @@ -7443,12 +7475,13 @@ turnstileToken = token; // Retry the request with new token - const retryPayload = { coords, colors, t: token }; + const retryPayload = { coords, colors, t: token, fp: fpStr32 }; + var wasmtoken = await createWasmToken(regionX, regionY, retryPayload); const retryRes = await fetch( `https://backend.wplace.live/s0/pixel/${regionX}/${regionY}`, { method: 'POST', - headers: { 'Content-Type': 'text/plain;charset=UTF-8' }, + headers: { 'Content-Type': 'text/plain;charset=UTF-8', "x-pawtect-token": wasmtoken }, credentials: 'include', body: JSON.stringify(retryPayload), } @@ -7512,13 +7545,13 @@ blockHeight: state.blockHeight, // Save ignore mask (as base64) with its dimensions resizeIgnoreMask: state.resizeIgnoreMask && - state.resizeSettings && - state.resizeSettings.width * state.resizeSettings.height === state.resizeIgnoreMask.length + state.resizeSettings && + state.resizeSettings.width * state.resizeSettings.height === state.resizeIgnoreMask.length ? { - w: state.resizeSettings.width, - h: state.resizeSettings.height, - data: btoa(String.fromCharCode(...state.resizeIgnoreMask)), - } + w: state.resizeSettings.width, + h: state.resizeSettings.height, + data: btoa(String.fromCharCode(...state.resizeIgnoreMask)), + } : null, // Notifications notificationsEnabled: state.notificationsEnabled, notifyOnChargesReached: state.notifyOnChargesReached, @@ -7816,6 +7849,164 @@ // Load theme preference immediately on startup before creating UI loadThemePreference(); applyTheme(); + const isExactlyEqual = (a, b) => a?.[Object.keys(a)[0]]?.variant === b?.[Object.keys(b)[0]]?.variant; + var pawtect_chunk = null; + + //find module if pawtect_chunk is null + pawtect_chunk ??= await findTokenModule("pawtect_wasm_bg.wasm"); + + async function createWasmToken(regionX, regionY, payload) { + try { + // Load the Pawtect module and WASM + const mod = await import(new URL('/_app/immutable/chunks/' + pawtect_chunk, location.origin).href); + let wasm; + try { + wasm = await mod._(); + console.log('✅ WASM initialized successfully'); + } catch (wasmError) { + console.error('❌ WASM initialization failed:', wasmError); + return null; + } + try { + try { + const me = await fetch(`https://backend.wplace.live/me`, { credentials: 'include' }).then(r => r.ok ? r.json() : null); + if (me?.id) { + mod.i(me.id); + console.log('✅ user ID set:', me.id); + } + if (me?.experiments) { + if (state.experiments == null) { + var item = Object.keys(me.experiments).find((v, _, __) => v.contains("pawtect")) ?? null; + if (item) { + if (me.experiments[item]?.variant && typeof (me.experiments[item]?.variant) === "string") { + localStorage.setItem("exp_wbot", me.experiments); + } + } + } + else { + var item = Object.keys(me.experiments).find((v, _, __) => v.contains("pawtect")) ?? null; + if (item) { + if (!isExactlyEqual(state.experiments, me.experiments)) { + alert("WPlace updated their PAWTECT Variant! REPORT TO WPLACE BOT DEVELOPERS") + } + } + } + } + } catch { } + } catch (userIdError) { + console.log('⚠️ Error setting user ID:', userIdError.message); + } + try { + const testUrl = `https://backend.wplace.live/s0/pixel/${regionX}/${regionY}`; + if (mod.r) { + mod.r(testUrl); + console.log('✅ Request URL set:', testUrl); + } else { + console.log('⚠️ request_url function (mod.r) not available'); + } + } catch (urlError) { + console.log('⚠️ Error setting request URL:', urlError.message); + } + + // Create test payload + + console.log('📝 payload:', payload); + + // Encode payload + const enc = new TextEncoder(); + const dec = new TextDecoder(); + const bodyStr = JSON.stringify(payload); + const bytes = enc.encode(bodyStr); + console.log('📏 Payload size:', bytes.length, 'bytes'); + console.log('📄 Payload string:', bodyStr); + + // Allocate WASM memory with validation + let inPtr; + try { + if (!wasm.__wbindgen_malloc) { + console.error('❌ __wbindgen_malloc function not found'); + return null; + } + + inPtr = wasm.__wbindgen_malloc(bytes.length, 1); + console.log('✅ WASM memory allocated, pointer:', inPtr); + + // Copy data to WASM memory + const wasmBuffer = new Uint8Array(wasm.memory.buffer, inPtr, bytes.length); + wasmBuffer.set(bytes); + console.log('✅ Data copied to WASM memory'); + } catch (memError) { + console.error('❌ Memory allocation error:', memError); + return null; + } + + // Call the WASM function + console.log('🚀 Calling get_pawtected_endpoint_payload...'); + let outPtr, outLen, token; + try { + const result = wasm.get_pawtected_endpoint_payload(inPtr, bytes.length); + console.log('✅ Function called, result type:', typeof result, result); + + if (Array.isArray(result) && result.length === 2) { + [outPtr, outLen] = result; + console.log('✅ Got output pointer:', outPtr, 'length:', outLen); + + // Decode the result + const outputBuffer = new Uint8Array(wasm.memory.buffer, outPtr, outLen); + token = dec.decode(outputBuffer); + console.log('✅ Token decoded successfully'); + } else { + console.error('❌ Unexpected function result format:', result); + return null; + } + } catch (funcError) { + console.error('❌ Function call error:', funcError); + console.error('Stack trace:', funcError.stack); + return null; + } + + // Cleanup memory + try { + if (wasm.__wbindgen_free && outPtr && outLen) { + wasm.__wbindgen_free(outPtr, outLen, 1); + console.log('✅ Output memory freed'); + } + if (wasm.__wbindgen_free && inPtr) { + wasm.__wbindgen_free(inPtr, bytes.length, 1); + console.log('✅ Input memory freed'); + } + } catch (cleanupError) { + console.log('⚠️ Cleanup warning:', cleanupError.message); + } + + // Display results + console.log(''); + console.log('🎉 SUCCESS!'); + console.log('🔑 Full token:'); + console.log(token); + return token; + } catch (error) { + console.error('❌ Failed to generate fp parameter:', error); + return null; + } + } + + async function findTokenModule(str) { + console.log('🔎 Searching for wasm Module...'); + const links = Array.from(document.querySelectorAll('link[rel="modulepreload"][href$=".js"]')); + + for (const link of links) { + try { + const url = new URL(link.getAttribute("href"), location.origin).href; + const code = await fetch(url).then(r => r.text()); + if (code.includes(str)) { + console.log('✅ Found wasm Module...'); + return url.split('/').pop(); + } + } catch { } + } + console.error(`❌ Could not find Pawtect chunk: `, error); + } createUI().then(() => { // Generate token automatically after UI is ready diff --git a/auto-image-styles.css b/auto-image-styles.css index 95b1ffa8..12d2c092 100644 --- a/auto-image-styles.css +++ b/auto-image-styles.css @@ -10,6 +10,7 @@ /* Import theme files - classic is default */ @import url('https://wplace-autobot.github.io/WPlace-AutoBOT/main/themes/classic.css'); @import url('https://wplace-autobot.github.io/WPlace-AutoBOT/main/themes/classic-light.css'); +@import url('https://wplace-autobot.github.io/WPlace-AutoBOT/main/themes/acrylic.css'); @import url('https://wplace-autobot.github.io/WPlace-AutoBOT/main/themes/neon.css'); /* Default :root CSS variables for 100% classic theme compliance */ diff --git a/lang/de.json b/lang/de.json new file mode 100644 index 00000000..b2d2f4bc --- /dev/null +++ b/lang/de.json @@ -0,0 +1,74 @@ +{ + "title": "WPlace Auto-Image", + "toggleOverlay": "Vorschau umschalten", + "scanColors": "Farben scannen", + "uploadImage": "Bild hochladen", + "resizeImage": "Bildgröße ändern", + "selectPosition": "Position wählen", + "startPainting": "Malen starten", + "stopPainting": "Malen stoppen", + "checkingColors": "🔍 Verfügbare Farben werden geprüft...", + "noColorsFound": "❌ Öffne die Farbpalette und versuche es erneut!", + "colorsFound": "✅ {count} verfügbare Farben gefunden. Bereit zum Hochladen.", + "loadingImage": "🖼️ Bild wird geladen...", + "imageLoaded": "✅ Bild mit {count} gültigen Pixeln geladen", + "imageError": "❌ Fehler beim Laden des Bildes", + "selectPositionAlert": "Male den ersten Pixel an der Stelle, an der dein Kunstwerk beginnen soll!", + "waitingPosition": "👆 Warte, bis du den Referenzpixel malst...", + "positionSet": "✅ Position gefunden!", + "positionTimeout": "❌ Zeitüberschreitung bei der Positionswahl", + "startPaintingMsg": "🎨 Malvorgang wird gestartet...", + "paintingProgress": "🧱 Fortschritt: {painted}/{total} Pixel...", + "noCharges": "⌛ Keine Ladungen. Warte {time}...", + "paintingStopped": "⏹️ Malen vom Benutzer gestoppt", + "paintingComplete": "✅ Malvorgang abgeschlossen! {count} Pixel gemalt.", + "paintingError": "❌ Fehler während des Malens", + "missingRequirements": "❌ Lade zuerst ein Bild und wähle eine Position", + "progress": "Fortschritt", + "pixels": "Pixel", + "charges": "Ladungen", + "estimatedTime": "Geschätzte Zeit", + "initMessage": "Klicke auf 'Bild hochladen', um zu beginnen", + "waitingInit": "Warte auf Initialisierung...", + "initializingToken": "🔧 Turnstile-Token-Generator wird initialisiert...", + "tokenReady": "✅ Token-Generator bereit - du kannst jetzt malen!", + "tokenRetryLater": "⚠️ Token-Generator versucht es später erneut", + "resizeSuccess": "✅ Bildgröße auf {width}x{height} geändert", + "paintingPaused": "⏸️ Malen pausiert bei X: {x}, Y: {y}", + "captchaNeeded": "❗ Token-Generierung fehlgeschlagen. Bitte später erneut versuchen.", + "saveData": "Fortschritt speichern", + "loadData": "Fortschritt laden", + "saveToFile": "In Datei speichern", + "loadFromFile": "Aus Datei laden", + "dataManager": "Datenverwaltung", + "autoSaved": "✅ Fortschritt automatisch gespeichert", + "dataLoaded": "✅ Fortschritt erfolgreich geladen", + "fileSaved": "✅ Fortschritt erfolgreich in Datei gespeichert", + "fileLoaded": "✅ Fortschritt erfolgreich aus Datei geladen", + "noSavedData": "❌ Kein gespeicherter Fortschritt gefunden", + "savedDataFound": "✅ Gespeicherter Fortschritt gefunden! Laden, um fortzufahren?", + "savedDate": "Gespeichert am: {date}", + "clickLoadToContinue": "Klicke auf 'Fortschritt laden', um fortzufahren.", + "fileError": "❌ Fehler bei der Dateiverarbeitung", + "invalidFileFormat": "❌ Ungültiges Dateiformat", + "paintingSpeed": "Malgeschwindigkeit", + "pixelsPerSecond": "Pixel/Sekunde", + "speedSetting": "Geschwindigkeit: {speed} Pixel/Sek", + "settings": "Einstellungen", + "botSettings": "Bot-Einstellungen", + "close": "Schließen", + "language": "Sprache", + "themeSettings": "Design-Einstellungen", + "themeSettingsDesc": "Wähle dein bevorzugtes Design für die Oberfläche.", + "languageSelectDesc": "Wähle deine bevorzugte Sprache. Änderungen wirken sofort.", + "autoCaptcha": "Auto-CAPTCHA Löser (Turnstile)", + "autoCaptchaDesc": "Generiert Turnstile-Tokens automatisch über integrierten Generator. Fällt auf Browser-Automatisierung zurück, falls nötig.", + "applySettings": "Einstellungen anwenden", + "settingsSaved": "✅ Einstellungen erfolgreich gespeichert!", + "cooldownSettings": "Abkühl-Einstellungen", + "waitCharges": "Warte bis Ladungen erreichen", + "captchaSolving": "🔑 Generiere Turnstile-Token...", + "captchaFailed": "❌ Turnstile-Token-Generierung fehlgeschlagen. Versuche Fallback-Methode...", + "automation": "Automatisierung", + "noChargesThreshold": "⌛ Warte bis {threshold} Ladungen erreicht sind. Aktuell {current}. Nächste in {time}..." +} \ No newline at end of file diff --git a/splitProgressScript.js b/splitProgressScript.js new file mode 100644 index 00000000..746c1cea --- /dev/null +++ b/splitProgressScript.js @@ -0,0 +1,71 @@ +// Parse input JSON +let e = await t.text(); +let s = JSON.parse(e); + +let { imageData: l } = s; +let { pixels: r } = l; + +// Count total non-transparent pixels +let a = 0; +for (let i = 3; i < r.length; i += 4) { + if (r[i] > 0) a++; +} + +let c = Math.floor(a / o); +let x = []; + +// Split the work into "o" parts +for (let part = 0; part < o; part++) { + // Deep clone the original object + let tClone = JSON.parse(JSON.stringify(s)); + let lClone = [...r]; + + let i = 0; + for (let idx = 3; idx < lClone.length; idx += 4) { + if (r[idx] > 0) { + let inThisPart = ( + part === 0 + ? i < c + : part === o - 1 + ? i >= part * c + : i >= part * c && i < (part + 1) * c + ); + + if (!inThisPart) { + lClone[idx] = 0; + } + i++; + } + } + + // Replace pixels with modified clone + tClone.imageData.pixels = lClone; + + // Count visible pixels for this part + let d = 0; + for (let idx = 3; idx < lClone.length; idx += 4) { + if (lClone[idx] > 0) d++; + } + + // Add state + tClone.state = { + totalPixels: d, + paintedPixels: 0, + }; + + // Create downloadable JSON blob + let blob = new Blob([JSON.stringify(tClone, null, 2)], { + type: "application/json", + }); + let url = URL.createObjectURL(blob); + + // Push info to results + x.push({ + botNumber: part + 1, + fileName: `wplace-bot-${part + 1}-progress.json`, + visiblePixels: d, + totalPixels: a, + paintablePixels: d, + downloadUrl: url, + }); +} diff --git a/themes/acrylic.css b/themes/acrylic.css new file mode 100644 index 00000000..fbf1afb9 --- /dev/null +++ b/themes/acrylic.css @@ -0,0 +1,603 @@ +/* WPlace Auto-Image Bot - Acrylic Theme */ +/* Beautiful theme with translucent blurred panels */ + +@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); + +@font-face { + font-family: 'Apple Color Emoji'; + src: url('https://raw.githubusercontent.com/GORAlexComp/AppleColorEmojiFont/refs/heads/main/fonts/AppleColorEmoji.ttf'); +} + +/* Main Container */ +.wplace-theme-acrylic #wplace-image-bot-container { + background: var(--wplace-primary); + color: var(--wplace-text); + border-radius: var(--wplace-radius); + box-shadow: none; + backdrop-filter: var(--wplace-backdrop); + border: var(--wplace-border-width) var(--wplace-border-style) + var(--wplace-border-color); + min-width: 300px; +} + +.wplace-theme-acrylic #wplace-image-bot-container * { + font-size: 15px; + line-height: normal; +} + +.wplace-theme-acrylic .wplace-content { + display: flex; + flex-direction: column; + gap: 10px; + padding: 10px; +} + +#wplace-image-bot-container.wplace-dragging { + transition: none !important; + box-shadow: none !important; + transform: none !important; +} + +/* Stats */ +.wplace-theme-acrylic #wplace-stats-container { + background: var(--wplace-primary); + color: var(--wplace-text); + border-radius: var(--wplace-radius); + box-shadow: none; + backdrop-filter: var(--wplace-backdrop); + border: var(--wplace-border-width) var(--wplace-border-style) + var(--wplace-border-color); +} + +.wplace-theme-acrylic .wplace-stats { + margin-bottom: 0; +} + +.wplace-theme-acrylic .wplace-colors-section { + border-top: none; + margin: 0; +} + +/* Settings Container */ +.wplace-theme-acrylic #wplace-settings-container { + background: var(--wplace-primary) !important; + color: var(--wplace-text) !important; + border-radius: var(--wplace-radius) !important; + box-shadow: none !important; + backdrop-filter: var(--wplace-backdrop) !important; + border: var(--wplace-border-width) var(--wplace-border-style) + var(--wplace-border-color) !important; + max-width: 400px !important; +} + +.wplace-theme-acrylic .wplace-settings-header { + background: transparent; + padding: 0; +} + +.wplace-theme-acrylic .wplace-settings-header:hover { + background: transparent !important; +} + +.wplace-theme-acrylic .wplace-settings-icon { + animation: none; + font-size: 15px; +} + +.wplace-theme-acrylic .wplace-settings-content { + padding: 10px; + display: flex; + flex-direction: column; + gap: 10px; +} + +.wplace-theme-acrylic .wplace-settings-footer { + border-top: none; + padding: 10px; +} + +.wplace-theme-acrylic .wplace-settings-section { + margin: 0; +} + +.wplace-theme-acrylic .wplace-settings-section-wrapper, +.wplace-theme-acrylic .wplace-overlay-wrapper, +.wplace-theme-acrylic .wplace-batch-controls { + padding: 0 !important; + background: transparent !important; + border: none !important; +} + +/* Headers */ +.wplace-theme-acrylic .wplace-header, +.wplace-theme-acrylic .wplace-settings-title-wrapper { + height: 40px; + padding: 7px 7px 7px 10px; + font-weight: 600; + background: var(--wplace-accent); + color: var(--wplace-highlight); +} + +.wplace-theme-acrylic .wplace-header span, +.wplace-theme-acrylic .wplace-settings-title { + max-width: 150px; + font-size: 15px; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.wplace-theme-acrylic .wplace-header-controls #compactBtn { + display: none; +} + +.wplace-theme-acrylic .wplace-header-btn, +.wplace-theme-acrylic .wplace-settings-close-btn { + background: #2e2e2e; + color: var(--wplace-highlight); + border: none; + font-size: 12px; + border-radius: 4px; + width: 24px; + height: 24px; +} + +.wplace-theme-acrylic .wplace-header-btn i { + font-size: 12px !important; +} + +.wplace-theme-acrylic .wplace-header-btn:hover, +.wplace-theme-acrylic .wplace-settings-close-btn:hover { + background: transparent; + transform: none; +} + +/* Sections */ +.wplace-theme-acrylic .wplace-section { + display: flex; + flex-direction: column; + gap: 8px; + background: transparent; + padding: 0; + border: none; + margin: 0; +} + +.wplace-theme-acrylic .wplace-section-title { + color: var(--wplace-highlight); + text-transform: capitalize; + font-size: 13px; + font-weight: 600; + pointer-events: none; + letter-spacing: unset; +} + +.wplace-theme-acrylic .wplace-section-title i { + display: none; +} + +.wplace-theme-acrylic .wplace-status-section { + background: transparent; + padding: 0; + margin: 0; + border: none; + display: flex; + flex-direction: column; + gap: 8px; +} + +/* Status Styling */ +.wplace-theme-acrylic .wplace-stats { + background: transparent; + padding: 0; + border: none; +} + +.wplace-theme-acrylic .wplace-stat-value { + color: var(--wplace-highlight); +} + +.wplace-theme-acrylic .wplace-status { + border-radius: var(--wplace-radius); + border: none; + box-shadow: none; + padding: 10px; + font-weight: 500; +} + +.wplace-theme-acrylic .status-default { + background: color-mix(in srgb, white 15%, transparent) !important; +} + +.wplace-theme-acrylic .status-success { + background: color-mix(in srgb, var(--wplace-success) 15%, transparent); + color: var(--wplace-success); +} + +.wplace-theme-acrylic .status-error { + background: color-mix(in srgb, var(--wplace-error) 15%, transparent); + color: var(--wplace-error); +} + +.wplace-theme-acrylic .status-warning { + background: color-mix(in srgb, var(--wplace-warning) 15%, transparent); + color: var(--wplace-warning); +} + +/* Buttons */ +.wplace-theme-acrylic .wplace-btn { + border-radius: 8px; + border: none; + height: max-content; + padding: 10px; + gap: 5px; + flex-direction: column; + align-items: flex-start; + line-height: normal; + text-align: left; + font-size: 15px !important; + box-shadow: none; +} + +.wplace-theme-acrylic .wplace-btn::before { + display: none; +} + +.wplace-theme-acrylic .wplace-btn:disabled { + box-shadow: none !important; +} + +.wplace-theme-acrylic .wplace-btn:hover:not(:disabled) { + transform: none; + animation: none; + box-shadow: none !important; + filter: brightness(0.9); +} + +.wplace-theme-acrylic .wplace-btn-primary, +.wplace-theme-acrylic .wplace-btn-upload { + background: white !important; + color: black !important; + border: none !important; +} + +.wplace-theme-acrylic .wplace-btn-upload:hover:not(:disabled) { + background: revert !important; +} + +.wplace-theme-acrylic .wplace-btn-secondary, +.wplace-theme-acrylic .wplace-btn-select, +.wplace-theme-acrylic .wplace-btn-file, +.wplace-theme-acrylic .wplace-btn-overlay { + background: var(--wplace-secondary); +} + +.wplace-theme-acrylic .wplace-btn-start { + background: var(--wplace-success); + color: white; +} + +.wplace-theme-acrylic .wplace-btn-stop { + background: var(--wplace-error); + color: white; +} + +.wplace-theme-acrylic .wplace-btn.active { + background: white; + color: black; + box-shadow: none !important; +} + +.wplace-theme-acrylic .wplace-btn.active i { + filter: none; +} + +.wplace-theme-acrylic .wplace-settings-apply-btn { + background: white; + color: black; + border-radius: 8px; +} + +/* Compact Input Buttons */ +.wplace-theme-acrylic .wplace-input-btn-small, +.wplace-theme-acrylic .wplace-input-btn-small:hover, +.wplace-theme-acrylic .wplace-input-btn-small:active { + background: white; + color: black; + border: none; + transform: none; + border-radius: 4px; + box-shadow: none; + font-weight: 500; + width: 25px; + height: 25px; +} + +/* Alerts */ +.wplace-theme-acrylic .wplace-alert-base { + border-radius: var(--wplace-radius); + backdrop-filter: var(--wplace-backdrop); + border: none; + box-shadow: none; +} + +.wplace-theme-acrylic .wplace-alert-info { + background: color-mix(in srgb, #0000e5 50%, transparent); +} + +.wplace-theme-acrylic .wplace-alert-success { + background: color-mix(in srgb, var(--wplace-success) 50%, transparent); +} + +.wplace-theme-acrylic .wplace-alert-error { + background: color-mix(in srgb, var(--wplace-error) 50%, transparent); +} + +.wplace-theme-acrylic .wplace-alert-warning { + background: color-mix(in srgb, var(--wplace-warning) 50%, transparent); +} + +/* Progress Bar */ +.wplace-theme-acrylic .wplace-progress { + background: var(--wplace-secondary); + border-radius: 4px; + margin: 0; + border: none; +} + +.wplace-theme-acrylic .wplace-progress-bar { + background: white; +} + +.wplace-theme-acrylic .wplace-progress-bar::after { + display: none; +} + +/* Form Controls */ +.wplace-theme-acrylic .wplace-settings-checkbox, +.wplace-theme-acrylic .wplace-notification-checkbox, +.wplace-theme-acrylic .wplace-speed-checkbox { + cursor: pointer; + width: 20px; + height: 20px; + flex-shrink: 0; + accent-color: var(--wplace-highlight); +} + +.wplace-theme-acrylic .wplace-settings-select, +.wplace-theme-acrylic .wplace-settings-number-input, +.wplace-theme-acrylic .wplace-cooldown-input, +.wplace-theme-acrylic .wplace-notification-interval-input { + background: rgb(255 255 255 / 10%); + color: white; + border: 1px solid rgb(255 255 255 / 25%); + border-radius: 8px; + box-shadow: none; + transition-duration: 0.3s; +} + +.wplace-theme-acrylic .wplace-settings-select:hover, +.wplace-theme-acrylic .wplace-settings-number-input:hover, +.wplace-theme-acrylic .wplace-cooldown-input:hover, +.wplace-theme-acrylic .wplace-notification-interval-input:hover { + border-color: rgb(255 255 255 / 50%); +} + +.wplace-theme-acrylic .wplace-settings-select:focus, +.wplace-theme-acrylic .wplace-settings-number-input:focus, +.wplace-theme-acrylic .wplace-cooldown-input:focus, +.wplace-theme-acrylic .wplace-notification-interval-input:focus { + border-color: white; +} + +.wplace-theme-acrylic .wplace-settings-option { + background: #2d3748; + color: white; +} + +.wplace-theme-acrylic .wplace-settings-select option { + background: #2d3748; + color: white; +} + +.wplace-theme-acrylic .wplace-cooldown-input { + border-radius: 4px !important; +} + +.wplace-theme-acrylic .wplace-cooldown-input:focus { + background: rgb(255 255 255 / 10%); + box-shadow: none; +} + +.wplace-theme-acrylic .wplace-overlay-opacity-value { + background-color: var(--wplace-secondary) !important; + border: none !important; +} + +/* Sliders */ +.wplace-theme-acrylic .wplace-slider, +.wplace-theme-acrylic .wplace-speed-slider, +.wplace-theme-acrylic .wplace-overlay-opacity-slider { + background: var(--wplace-secondary) !important; + border-radius: 3px !important; + height: 6px !important; +} + +.wplace-theme-acrylic .wplace-slider::-webkit-slider-thumb, +.wplace-theme-acrylic .resize-slider::-webkit-slider-thumb, +.wplace-theme-acrylic .wplace-speed-slider::-webkit-slider-thumb, +.wplace-theme-acrylic .wplace-overlay-opacity-slider::-webkit-slider-thumb { + width: 16px !important; + height: 16px !important; + border-radius: 4px !important; + background: white !important; + box-shadow: none !important; + transform: none !important; +} + +.wplace-theme-acrylic .wplace-speed-value { + background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); + border-radius: 8px; + color: white; + box-shadow: 0 3px 10px rgb(79 172 254 / 30%); + border: 1px solid rgb(255 255 255 / 20%); +} + +.wplace-theme-acrylic .resize-slider { + -webkit-appearance: revert; +} + +/* Layout Controls */ +.wplace-theme-acrylic .wplace-slider-container { + display: flex; + flex-direction: row; + align-items: center; + gap: 8px; + margin: 0; +} + +.wplace-theme-acrylic .wplace-input-label-compact { + color: rgba(255, 255, 255, 0.75); + margin-left: 4px; + text-transform: lowercase; + white-space: nowrap; +} + +.wplace-theme-acrylic .wplace-cooldown-control { + margin: 0; + display: flex; + flex-direction: column; + gap: 8px; +} + +.wplace-theme-acrylic .wplace-cooldown-control label { + font-weight: 400; + margin-bottom: 0; + display: block; +} + +.wplace-theme-acrylic .wplace-cooldown-input-group { + margin: 0; + background: transparent; +} + +/* Color Elements */ +.wplace-theme-acrylic .wplace-color-item-name { + color: #ccc; +} + +.wplace-theme-acrylic .wplace-color-swatch { + border: 1px solid rgb(255 255 255 / 20%); + border-radius: 4px; +} + +.wplace-theme-acrylic .wplace-color-swatch:not(.active) { + filter: grayscale(80%); +} + +.wplace-theme-acrylic .wplace-color-swatch.unavailable { + border-color: #666; +} + +.wplace-theme-acrylic .wplace-color-swatch.unavailable:not(.active) { + filter: grayscale(90%); +} + +.wplace-theme-acrylic .wplace-color-swatch.active::after { + text-shadow: 0 0 3px black; +} + +.wplace-theme-acrylic .wplace-stat-color-swatch { + border-radius: 3px; + border: 1px solid rgb(255 255 255 / 10%); + box-shadow: inset 0 0 2px rgb(0 0 0 / 50%); +} + +.wplace-theme-acrylic .wplace-stat-colors-grid { + background: var(--wplace-secondary); + border-radius: 8px; +} + +.wplace-theme-acrylic .wplace-color-divider { + background: rgb(255 255 255 / 10%); +} + +/* Icons */ +.wplace-theme-acrylic .wplace-icon-key, +.wplace-theme-acrylic .wplace-icon-robot, +.wplace-theme-acrylic .wplace-icon-speed, +.wplace-theme-acrylic .wplace-icon-bell, +.wplace-theme-acrylic .wplace-icon-palette, +.wplace-theme-acrylic .wplace-icon-globe, +.wplace-theme-acrylic .wplace-icon-paint, +.wplace-theme-acrylic .wplace-icon-eye, +.wplace-theme-acrylic .wplace-icon-compass, +.wplace-theme-acrylic .wplace-icon-route, +.wplace-theme-acrylic .wplace-icon-table, +.wplace-theme-acrylic .wplace-icon-dice { + color: white; +} + +/* Typography */ +.wplace-theme-acrylic .wplace-cooldown-unit { + display: none; +} + +.wplace-theme-acrylic .wplace-settings-toggle-title, +.wplace-theme-acrylic .wplace-overlay-opacity-label { + font-size: 15px !important; +} + +.wplace-theme-acrylic .wplace-settings-description, +.wplace-theme-acrylic .wplace-random-batch-description, +.wplace-theme-acrylic .wplace-settings-toggle-description { + font-size: 12px; + color: rgb(255 255 255 / 75%) !important; +} + +/* Turnstile Overlay */ +.wplace-theme-acrylic .wplace-turnstile-overlay { + background: var(--wplace-primary); + border-radius: var(--wplace-radius); + box-shadow: none; + backdrop-filter: var(--wplace-backdrop); + border: none; + padding: 16px !important; + color: var(--wplace-text) !important; +} + +.wplace-theme-acrylic .wplace-turnstile-hide-btn { + border-radius: 8px !important; + backdrop-filter: var(--wplace-backdrop) !important; + background: var(--wplace-primary) !important; + top: -25px !important; + right: 0 !important; + transition: all 0.3s ease !important; +} + +.wplace-theme-acrylic .wplace-turnstile-hide-btn:hover { + background: white !important; + color: black !important; +} + +/* Resize Tools */ +.wplace-theme-acrylic .resize-tools button { + border-radius: 6px; + border: 1px solid rgb(255 255 255 / 20%); + background: rgb(255 255 255 / 6%); + color: #fff; +} + +.wplace-theme-acrylic .resize-overlay { + background: rgb(0 0 0 / 50%); +} + +/* TODO: More resize menu styles */ +.wplace-theme-acrylic .resize-container { + background: var(--wplace-secondary); + backdrop-filter: var(--wplace-backdrop); + border: none; + border-radius: var(--wplace-radius); + color: var(--wplace-text); +}