Animated BG, Text/Font changer, UI controls with maximize feature, diamond-locked premium colors/fonts.
// ==UserScript==
// @name Zebra Type Customizer
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Animated BG, Text/Font changer, UI controls with maximize feature, diamond-locked premium colors/fonts.
// @author MyUserScripts
// @match https://zebratype.org/*
// @match https://zebratype.org/race
// @grant none
// ==/UserScript==
(function() {
'use strict';
const bgColors = [
{ val: "linear-gradient(90deg, #ff9a9e, #fad0c4)", name: "Peach" },
{ val: "linear-gradient(90deg, #a18cd1, #fbc2eb)", name: "Lavender" },
{ val: "linear-gradient(90deg, #84fab0, #8fd3f4)", name: "Seafoam" },
{ val: "linear-gradient(90deg, #ffecd2, #fcb69f)", name: "Sunset" },
{ val: "linear-gradient(90deg, #f093fb, #f5576c)", name: "Rose" },
{ val: "linear-gradient(90deg, #89f7fe, #66a6ff)", name: "Sky" },
{ val: "linear-gradient(90deg, #d4fc79, #96e6a1)", name: "Lime" },
{ val: "linear-gradient(90deg, #cfd9df, #e2ebf0)", name: "Silver" },
{ val: "linear-gradient(90deg, #ff9a9e, #fecfef)", name: "Cherry" },
{ val: "linear-gradient(90deg, #bf953f, #fcf6ba, #b38728, #fbf5b7, #aa771c, #bf953f)", name: "Gold", locked: true, special: true },
{ val: "linear-gradient(90deg, red, orange, yellow, green, blue, indigo, violet, red)", name: "Rainbow", locked: true, special: true }
];
const textColors = [
{ val: "linear-gradient(90deg, #ff5e62, #ff9966)" }, { val: "linear-gradient(90deg, #f0f270, #ffcc00)" },
{ val: "linear-gradient(90deg, #00c6ff, #0072ff)" }, { val: "linear-gradient(90deg, #8e2de2, #4a00e0)" },
{ val: "linear-gradient(90deg, #ff00cc, #333399)" }, { val: "linear-gradient(90deg, #00ff9f, #00aa6b)" },
{ val: "linear-gradient(90deg, #ffffff, #aaaaaa)" }, { val: "linear-gradient(90deg, #bf953f, #fcf6ba)" },
{ val: "linear-gradient(90deg, red, violet)" }
];
const fonts = [
{ name: "Arial", val: "Arial, sans-serif" },
{ name: "Courier", val: "'Courier New', Courier, monospace" },
{ name: "Impact", val: "Impact, Charcoal, sans-serif" },
{ name: "Verdana", val: "Verdana, Geneva, sans-serif" },
{ name: "Georgia", val: "Georgia, serif" },
{ name: "Comic Sans", val: "'Comic Sans MS', cursive" },
{ name: "Monoton", val: "'Monoton', cursive", locked: true },
{ name: "Bangers", val: "'Bangers', cursive", locked: true },
{ name: "Orbitron", val: "'Orbitron', sans-serif", locked: true }
];
const style = document.createElement('style');
style.innerHTML = `
@keyframes scrollBG { 0% { background-position: 0% 50%; } 100% { background-position: 200% 50%; } }
@keyframes glow { 0% { box-shadow: 0 0 5px #fff; } 50% { box-shadow: 0 0 20px #00d4ff; } 100% { box-shadow: 0 0 5px #fff; } }
.zt-panel { position: fixed; top: 20px; right: 20px; width: 280px; background: rgba(0, 0, 0, 0.85); border: 2px solid transparent; border-radius: 20px; padding: 15px; z-index: 10000; color: #fff; font-family: 'Segoe UI', sans-serif; backdrop-filter: blur(10px); background-clip: padding-box; animation: glow 3s infinite alternate; }
.zt-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; border-bottom: 1px solid rgba(255,255,255,0.2); padding-bottom: 8px; cursor: move; font-weight: bold; font-size: 13px; letter-spacing: 1px; }
.zt-controls { cursor: pointer; display: flex; gap: 10px; font-weight: bold; align-items: center; color: #aaa; transition: 0.3s; }
.zt-controls span:hover { color: #fff; transform: scale(1.2); }
.zt-sec { margin-top: 10px; font-weight: 800; font-size: 9px; color: #00d4ff; text-transform: uppercase; margin-bottom: 8px; letter-spacing: 1.5px; }
.zt-row { display: flex; flex-wrap: wrap; gap: 6px; }
.zt-btn { width: 28px; height: 28px; border-radius: 10px; border: 2px solid rgba(255,255,255,0.1); cursor: pointer; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); position: relative; background-size: 200% 200% !important; animation: scrollBG 4s linear infinite; display: flex; align-items: center; justify-content: center; }
.zt-btn:hover { transform: scale(1.1); border-color: #fff; box-shadow: 0 0 10px rgba(255,255,255,0.2); }
.zt-font-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.zt-font-btn { position: relative; padding: 6px 4px; border-radius: 8px; background: rgba(255,255,255,0.05); color: #ddd; border: 1px solid rgba(255,255,255,0.1); cursor: pointer; text-align: center; font-size: 10px; transition: 0.3s; }
.zt-font-btn:hover { background: rgba(0, 212, 255, 0.2); border-color: #00d4ff; color: #fff; }
.diamond-mini { position: absolute; top: -7px; left: -7px; font-size: 9px; pointer-events: none; filter: drop-shadow(0 0 2px #fff); }
.minimized { height: 35px; overflow: hidden; }
.maximized { width: 95vw !important; height: 85vh !important; }
.hidden { display: none; }
`;
document.head.appendChild(style);
const settings = { bgGrad: 'linear-gradient(90deg, #000, #222)', textCol: 'transparent', font: 'Arial, sans-serif' };
function playErrorSound() {
try {
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioCtx = new AudioContext();
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.connect(gain); gain.connect(audioCtx.destination);
osc.type = 'sine'; osc.frequency.setValueAtTime(200, audioCtx.currentTime);
gain.gain.setValueAtTime(0.1, audioCtx.currentTime);
osc.start(); osc.stop(audioCtx.currentTime + 0.1);
} catch(e) { console.log("Audio skipped"); }
}
function updatePage() {
document.body.style.background = settings.bgGrad;
document.body.style.backgroundSize = "200% 100%";
document.body.style.backgroundAttachment = "fixed";
// Target specifically text inside main game elements or generally within panels
// Using -webkit-background-clip: text to apply gradient to text
const gameTextElements = document.querySelectorAll('.panel, .text-display, .game-text');
gameTextElements.forEach(el => {
el.style.backgroundImage = settings.textCol;
el.style.webkitBackgroundClip = "text";
el.style.backgroundClip = "text";
el.style.color = "transparent";
el.style.fontFamily = settings.font;
});
}
const panel = document.createElement('div');
panel.className = 'zt-panel';
panel.innerHTML = `
<div class="zt-header" id="zt-drag">
<div>✨ Zebra Type Customizer</div>
<div class="zt-controls"><span id="min">-</span><span id="max">□</span><span id="close">×</span></div>
</div>
<div id="zt-content"></div>
`;
document.body.appendChild(panel);
document.getElementById('close').onclick = () => panel.remove();
document.getElementById('min').onclick = () => {
document.getElementById('zt-content').classList.toggle('hidden');
panel.classList.toggle('minimized');
};
document.getElementById('max').onclick = () => panel.classList.toggle('maximized');
const content = panel.querySelector('#zt-content');
const bgSec = document.createElement('div'); bgSec.className = 'zt-sec'; bgSec.innerText = 'Background'; content.appendChild(bgSec);
const bgRow = document.createElement('div'); bgRow.className = 'zt-row';
bgColors.forEach(item => {
const btn = document.createElement('button');
btn.className = 'zt-btn';
btn.style.background = item.val;
if (item.locked) btn.innerHTML = `<span class="diamond-mini">💎</span>`;
btn.onclick = () => {
if (item.locked) { playErrorSound(); }
else { settings.bgGrad = item.val; updatePage(); }
};
bgRow.appendChild(btn);
});
content.appendChild(bgRow);
const txtSec = document.createElement('div'); txtSec.className = 'zt-sec'; txtSec.innerText = 'Text Color'; content.appendChild(txtSec);
const txtRow = document.createElement('div'); txtRow.className = 'zt-row';
textColors.forEach(item => {
const btn = document.createElement('button');
btn.className = 'zt-btn';
btn.style.background = item.val;
btn.onclick = () => { settings.textCol = item.val; updatePage(); };
txtRow.appendChild(btn);
});
content.appendChild(txtRow);
const fontSec = document.createElement('div'); fontSec.className = 'zt-sec'; fontSec.innerText = 'Fonts'; content.appendChild(fontSec);
const fontGrid = document.createElement('div'); fontGrid.className = 'zt-font-grid';
fonts.forEach(f => {
const btn = document.createElement('button');
btn.className = 'zt-font-btn';
btn.style.fontFamily = f.val;
if (f.locked) btn.innerHTML = `<span class="diamond-mini">💎</span>${f.name}`;
else btn.innerText = f.name;
btn.onclick = () => {
if (f.locked) { playErrorSound(); }
else { settings.font = f.val; updatePage(); }
};
fontGrid.appendChild(btn);
});
content.appendChild(fontGrid);
let isDragging = false, offset = { x: 0, y: 0 };
const dragHandle = panel.querySelector('#zt-drag');
dragHandle.addEventListener('mousedown', (e) => { isDragging = true; offset = { x: e.clientX - panel.offsetLeft, y: e.clientY - panel.offsetTop }; });
document.addEventListener('mousemove', (e) => { if (isDragging) { panel.style.left = (e.clientX - offset.x) + 'px'; panel.style.top = (e.clientY - offset.y) + 'px'; panel.style.right = 'auto'; } });
document.addEventListener('mouseup', () => { isDragging = false; });
})();