Train button 1.12

Replaces the Train buttons in Torn Gym with 16 clickable, customizable train icons. Every train plays the same custom whistle sound (plays once per click), mobile-safe settings modal, and a monochrome settings icon placed next to the Gym title (with safe fallback).

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

Advertisement:

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

Advertisement:

// ==UserScript==
// @name         Train button 1.12
// @namespace    http://tampermonkey.net/
// @version      1.13
// @description  Replaces the Train buttons in Torn Gym with 16 clickable, customizable train icons. Every train plays the same custom whistle sound (plays once per click), mobile-safe settings modal, and a monochrome settings icon placed next to the Gym title (with safe fallback).
// @author       Slenk
// @match        https://www.torn.com/gym.php*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // --- Hangmotor: minden vonathoz UGYANAZ a saját (feltöltött) hang szól ---
    // Nincs többé szintetizált sípolás - egy közös mp3 fájlt játszunk le minden kattintásra.
    const TRAIN_SOUND_URL = 'https://media.vocaroo.com/mp3/16iqFB1aQ7iP';
    let trainAudio = null;

    function getTrainAudio() {
        if (!trainAudio) {
            trainAudio = new Audio(TRAIN_SOUND_URL);
            trainAudio.preload = 'auto';
        }
        return trainAudio;
    }

    function playTrainSound() {
        try {
            const audio = getTrainAudio();
            // Ha gyorsan egymás után kattintanak, mindig az elejéről szóljon újra.
            audio.currentTime = 0;
            const playPromise = audio.play();
            if (playPromise && typeof playPromise.catch === 'function') {
                playPromise.catch((e) => console.warn('Train sound play error:', e));
            }
        } catch (e) {
            console.warn('Train sound error:', e);
        }
    }

    // Az alapértelmezett színek a csatolt kép alapján
    const trainDefaultColors = {
        train1: '#F1C40F',
        train2: '#F1C40F',
        train3: '#F1C40F',
        train4: '#F1C40F',
        train5: '#F1C40F',
        train6: '#3498DB',
        train7: '#ECF0F1',
        train8: '#7F8C8D',
        train9: '#2980B9',
        train10: '#27AE60',
        train11: '#E74C3C',
        train12: '#2ECC71',
        train13: '#ECF0F1',
        train14: '#27AE60',
        train15: '#95A5A6',
        train16: '#229954'
    };

    function loadColors() {
        let saved = {};
        try { saved = JSON.parse(GM_getValue('trainColors', '{}')); } catch (e) { saved = {}; }
        return Object.assign({}, trainDefaultColors, saved);
    }

    let settings = {
        trainType: GM_getValue('trainType', 'train1'),
        trainColors: loadColors()
    };

    const trainIcons = {
        train1: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M10,45 L10,10 L40,10 L40,25 L75,25 L75,45 Z" fill="COLOR_PLACEHOLDER" stroke="#333" stroke-width="2"/>
          <rect x="8" y="5" width="34" height="5" fill="#C0392B" stroke="#333" stroke-width="2"/>
          <path d="M55,25 L55,8 L65,8 L65,25 Z" fill="#D35400" stroke="#333" stroke-width="2"/>
          <rect x="15" y="15" width="15" height="15" fill="#FFF" stroke="#333" stroke-width="2"/>
          <polygon points="75,45 90,45 85,35 75,35" fill="#C0392B" stroke="#333" stroke-width="2"/>
          <circle cx="25" cy="50" r="8" fill="#E74C3C" stroke="#333" stroke-width="2"/>
          <circle cx="45" cy="50" r="6" fill="#E74C3C" stroke="#333" stroke-width="2"/>
          <circle cx="65" cy="50" r="6" fill="#E74C3C" stroke="#333" stroke-width="2"/>
          <line x1="25" y1="50" x2="65" y2="50" stroke="#DDD" stroke-width="2"/>
        </svg>`,

        train2: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M10,40 L10,15 C10,10 15,10 20,10 L80,10 C90,10 95,20 95,40 Z" fill="#FFF" stroke="#333" stroke-width="2"/>
          <path d="M10,45 L95,45 C95,35 95,35 95,35 L10,35 Z" fill="COLOR_PLACEHOLDER" stroke="#333" stroke-width="2"/>
          <rect x="25" y="15" width="10" height="20" fill="COLOR_PLACEHOLDER" stroke="#333" stroke-width="2"/>
          <rect x="65" y="15" width="10" height="20" fill="COLOR_PLACEHOLDER" stroke="#333" stroke-width="2"/>
          <rect x="12" y="18" width="10" height="10" fill="#333" rx="1"/>
          <rect x="40" y="18" width="20" height="10" fill="#333" rx="1"/>
          <path d="M80,18 L88,18 C90,18 90,25 88,28 L80,28 Z" fill="#333"/>
          <circle cx="25" cy="50" r="6" fill="#555" stroke="#333" stroke-width="2"/>
          <circle cx="40" cy="50" r="6" fill="#555" stroke="#333" stroke-width="2"/>
          <circle cx="60" cy="50" r="6" fill="#555" stroke="#333" stroke-width="2"/>
          <circle cx="75" cy="50" r="6" fill="#555" stroke="#333" stroke-width="2"/>
        </svg>`,

        train3: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M10,40 L10,15 C10,12 12,10 15,10 L35,10 L35,25 L80,25 L80,40 Z" fill="COLOR_PLACEHOLDER" stroke="#333" stroke-width="2"/>
          <rect x="8" y="6" width="30" height="5" fill="#E74C3C" stroke="#333" stroke-width="2" rx="2"/>
          <rect x="45" y="25" width="4" height="15" fill="#F1C40F" stroke="#333" stroke-width="1"/>
          <rect x="65" y="25" width="4" height="15" fill="#F1C40F" stroke="#333" stroke-width="1"/>
          <path d="M68,25 L70,10 L82,10 L84,25 Z" fill="#2980B9" stroke="#333" stroke-width="2"/>
          <rect x="15" y="15" width="7" height="10" fill="#FFF" stroke="#333" stroke-width="2"/>
          <rect x="25" y="15" width="7" height="10" fill="#FFF" stroke="#333" stroke-width="2"/>
          <polygon points="80,40 95,50 80,50" fill="#E74C3C" stroke="#333" stroke-width="2"/>
          <circle cx="20" cy="45" r="9" fill="#CCC" stroke="#333" stroke-width="2"/>
          <circle cx="45" cy="48" r="6" fill="#CCC" stroke="#333" stroke-width="2"/>
          <circle cx="65" cy="48" r="6" fill="#CCC" stroke="#333" stroke-width="2"/>
          <circle cx="85" cy="48" r="6" fill="#CCC" stroke="#333" stroke-width="2"/>
          <line x1="20" y1="45" x2="85" y2="48" stroke="#777" stroke-width="2"/>
        </svg>`,

        train4: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M5,45 L10,15 L35,15 L40,5 L80,5 L85,25 L95,25 L95,45 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="3"/>
          <circle cx="15" cy="25" r="1.5" fill="#FFF"/><circle cx="25" cy="25" r="1.5" fill="#FFF"/><circle cx="35" cy="25" r="1.5" fill="#FFF"/>
          <rect x="50" y="12" width="10" height="8" fill="#111" stroke="#555" stroke-width="2"/>
          <rect x="65" y="12" width="10" height="8" fill="#111" stroke="#555" stroke-width="2"/>
          <path d="M95,45 L100,55 L85,55 L85,45 Z" fill="#444" stroke="#222" stroke-width="2"/>
          <circle cx="25" cy="50" r="7" fill="#555" stroke="#222" stroke-width="2"/>
          <circle cx="50" cy="50" r="7" fill="#555" stroke="#222" stroke-width="2"/>
          <circle cx="75" cy="50" r="7" fill="#555" stroke="#222" stroke-width="2"/>
          <line x1="25" y1="50" x2="75" y2="50" stroke="#888" stroke-width="3"/>
        </svg>`,

        train5: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M5,45 L5,25 C5,15 20,15 30,15 L70,15 C90,15 95,35 95,45 Z" fill="COLOR_PLACEHOLDER" stroke="#333" stroke-width="2"/>
          <path d="M25,20 L65,20 C80,20 85,28 85,30 L20,30 C20,25 22,20 25,20 Z" fill="#222"/>
          <line x1="5" y1="38" x2="92" y2="38" stroke="#FFF" stroke-width="1.5"/>
          <path d="M15,45 L25,45 A 5 5 0 0 1 35 45 L55,45 A 5 5 0 0 1 65 45 L75,45 A 5 5 0 0 1 85 45 L95,45 L95,50 L5,50 Z" fill="#444" stroke="#333" stroke-width="2"/>
          <circle cx="30" cy="48" r="4" fill="#111"/>
          <circle cx="60" cy="48" r="4" fill="#111"/>
          <circle cx="80" cy="48" r="4" fill="#111"/>
        </svg>`,

        train6: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M10,42 L10,12 C10,10 12,8 15,8 L85,8 C92,8 95,12 95,42 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="18" y="15" width="14" height="20" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="42" y="15" width="14" height="20" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="66" y="15" width="14" height="20" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="10" y="38" width="85" height="4" fill="#E67E22"/>
          <circle cx="28" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
          <circle cx="72" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
          <path d="M95,40 L100,40 L100,44 L95,44" fill="#555" stroke="#222"/>
        </svg>`,

        train7: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M15,40 L15,15 C15,10 25,10 40,10 L65,10 C85,10 95,25 95,40 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="22" y="18" width="8" height="10" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="35" y="18" width="8" height="10" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="48" y="18" width="8" height="10" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <path d="M61,18 L73,18 C76,18 80,25 80,28 L61,28 Z" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <line x1="20" y1="32" x2="85" y2="32" stroke="#E74C3C" stroke-width="1.5"/>
          <rect x="10" y="40" width="85" height="6" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
        </svg>`,

        train8: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <rect x="15" y="10" width="20" height="25" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="35" y="18" width="40" height="17" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="12" y="8" width="26" height="4" fill="#D35400" stroke="#222" stroke-width="1.5"/>
          <path d="M58,18 L58,8 L66,8 L66,18 Z" fill="#2980B9" stroke="#222" stroke-width="1.5"/>
          <rect x="20" y="16" width="10" height="10" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <polygon points="75,35 85,35 90,45 75,45" fill="#D35400" stroke="#222" stroke-width="1.5"/>
          <circle cx="28" cy="45" r="7" fill="#555" stroke="#222" stroke-width="2"/>
          <circle cx="48" cy="45" r="7" fill="#555" stroke="#222" stroke-width="2"/>
          <circle cx="68" cy="45" r="7" fill="#555" stroke="#222" stroke-width="2"/>
          <line x1="28" y1="45" x2="68" y2="45" stroke="#DDD" stroke-width="2"/>
        </svg>`,

        train9: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M12,38 L12,12 C12,10 14,10 16,10 L84,10 C86,10 88,10 88,12 L88,38 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="14" y="8" width="26" height="4" fill="#D35400" stroke="#222" stroke-width="1.5"/>
          <rect x="20" y="16" width="8" height="10" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="32" y="16" width="8" height="10" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <line x1="60" y1="16" x2="60" y2="30" stroke="#333" stroke-width="1.5"/>
          <line x1="66" y1="16" x2="66" y2="30" stroke="#333" stroke-width="1.5"/>
          <line x1="72" y1="16" x2="72" y2="30" stroke="#333" stroke-width="1.5"/>
          <line x1="78" y1="16" x2="78" y2="30" stroke="#333" stroke-width="1.5"/>
          <rect x="8" y="38" width="84" height="4" fill="#333"/>
          <circle cx="25" cy="48" r="6" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="45" cy="48" r="6" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="65" cy="48" r="6" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
        </svg>`,

        train10: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <polyline points="25,12 35,4 45,12" fill="none" stroke="#555" stroke-width="2"/>
          <polyline points="55,12 65,4 75,12" fill="none" stroke="#555" stroke-width="2"/>
          <path d="M15,40 L15,18 C15,14 18,12 22,12 L78,12 C82,12 85,14 85,18 L85,40 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="25" y="18" width="10" height="8" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="45" y="18" width="10" height="8" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="65" y="18" width="10" height="8" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="15" y="34" width="70" height="6" fill="#2C3E50"/>
          <polygon points="15,40 10,48 20,48" fill="#D35400" stroke="#222" stroke-width="1.5"/>
          <polygon points="85,40 90,48 80,48" fill="#D35400" stroke="#222" stroke-width="1.5"/>
          <circle cx="30" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="50" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="70" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
        </svg>`,

        train11: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M5,42 L5,10 L75,10 C90,10 95,30 95,42 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="12" y="18" width="8" height="18" fill="#FFF" stroke="#222" stroke-width="1.5"/>
          <rect x="25" y="14" width="10" height="8" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="40" y="14" width="10" height="8" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="55" y="14" width="10" height="8" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="25" y="28" width="10" height="8" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="40" y="28" width="10" height="8" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="55" y="28" width="10" height="8" fill="#333" stroke="#222" stroke-width="1"/>
          <path d="M75,20 L85,20 C88,20 90,28 90,32 L75,32 Z" fill="#333"/>
          <circle cx="20" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="50" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="80" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
        </svg>`,

        train12: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <rect x="55" y="18" width="35" height="18" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="15" y="10" width="40" height="26" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <path d="M80,18 L80,10 L88,10 L88,18 Z" fill="#2C3E50" stroke="#222" stroke-width="1.5"/>
          <rect x="20" y="14" width="8" height="12" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="32" y="14" width="8" height="12" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="44" y="14" width="8" height="12" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <polygon points="90,36 100,45 85,45" fill="#E74C3C" stroke="#222" stroke-width="1.5"/>
          <circle cx="28" cy="44" r="9" fill="#E74C3C" stroke="#222" stroke-width="2"/>
          <circle cx="55" cy="46" r="6" fill="#E74C3C" stroke="#222" stroke-width="1.5"/>
          <circle cx="72" cy="46" r="6" fill="#E74C3C" stroke="#222" stroke-width="1.5"/>
          <circle cx="89" cy="46" r="6" fill="#E74C3C" stroke="#222" stroke-width="1.5"/>
          <line x1="28" y1="44" x2="89" y2="46" stroke="#ECF0F1" stroke-width="2"/>
        </svg>`,

        train13: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M5,40 L5,20 C5,15 15,15 30,15 L60,15 C85,15 95,30 95,40 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <line x1="5" y1="32" x2="90" y2="32" stroke="#2980B9" stroke-width="3"/>
          <rect x="15" y="20" width="8" height="8" rx="2" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="30" y="20" width="8" height="8" rx="2" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="45" y="20" width="8" height="8" rx="2" fill="#333" stroke="#222" stroke-width="1"/>
          <rect x="60" y="20" width="8" height="8" rx="2" fill="#333" stroke="#222" stroke-width="1"/>
          <path d="M75,20 L85,20 C88,20 90,25 90,28 L75,28 Z" fill="#333"/>
          <circle cx="20" cy="48" r="4" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="45" cy="48" r="4" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="70" cy="48" r="4" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
        </svg>`,

        train14: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <rect x="15" y="25" width="70" height="15" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="35" y="10" width="30" height="15" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="40" y="14" width="8" height="8" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <rect x="52" y="14" width="8" height="8" fill="#AEE6FA" stroke="#222" stroke-width="1.5"/>
          <path d="M42,10 L45,5 L55,5 L58,10 Z" fill="#2C3E50" stroke="#222"/>
          <line x1="15" y1="20" x2="85" y2="20" stroke="#F1C40F" stroke-width="1.5"/>
          <line x1="20" y1="20" x2="20" y2="25" stroke="#F1C40F" stroke-width="1.5"/>
          <line x1="30" y1="20" x2="30" y2="25" stroke="#F1C40F" stroke-width="1.5"/>
          <line x1="70" y1="20" x2="70" y2="25" stroke="#F1C40F" stroke-width="1.5"/>
          <line x1="80" y1="20" x2="80" y2="25" stroke="#F1C40F" stroke-width="1.5"/>
          <rect x="10" y="40" width="80" height="4" fill="#E74C3C" stroke="#222" stroke-width="1.5"/>
          <circle cx="25" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
          <circle cx="50" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
          <circle cx="75" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
        </svg>`,

        train15: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <path d="M10,30 L10,15 C10,10 15,10 25,10 L75,10 C85,10 95,20 95,30 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <path d="M10,42 L10,30 L95,30 L95,42 Z" fill="#E74C3C" stroke="#222" stroke-width="2"/>
          <rect x="30" y="16" width="10" height="10" fill="#333" stroke="#222" stroke-width="1.5"/>
          <rect x="45" y="16" width="10" height="10" fill="#333" stroke="#222" stroke-width="1.5"/>
          <rect x="60" y="16" width="10" height="10" fill="#333" stroke="#222" stroke-width="1.5"/>
          <path d="M78,16 L88,16 C90,16 92,20 92,26 L78,26 Z" fill="#333"/>
          <rect x="15" y="16" width="10" height="20" fill="#FFF" stroke="#222" stroke-width="1.5"/>
          <circle cx="25" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
          <circle cx="45" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
          <circle cx="75" cy="48" r="5" fill="#555" stroke="#222" stroke-width="1.5"/>
        </svg>`,

        train16: `<svg class="train-icon-btn" viewBox="0 0 100 60" width="60" height="36">
          <polyline points="25,12 35,4 45,12" fill="none" stroke="#555" stroke-width="2"/>
          <polyline points="55,12 65,4 75,12" fill="none" stroke="#555" stroke-width="2"/>
          <path d="M15,40 L15,18 C15,12 18,12 25,12 L75,12 C82,12 85,15 90,25 L95,40 Z" fill="COLOR_PLACEHOLDER" stroke="#222" stroke-width="2"/>
          <rect x="25" y="18" width="40" height="8" fill="#333" stroke="#222" stroke-width="1.5"/>
          <line x1="15" y1="32" x2="92" y2="32" stroke="#E74C3C" stroke-width="3"/>
          <path d="M88,40 L95,40 L95,45 C95,48 90,48 85,45 Z" fill="#E74C3C" stroke="#222" stroke-width="1.5"/>
          <circle cx="30" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="50" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
          <circle cx="70" cy="48" r="5" fill="#7F8C8D" stroke="#222" stroke-width="1.5"/>
        </svg>`
    };

    // Monokróm vonat + fogaskerék ikon a beállítás gombhoz
    const settingsIconSvg = `<svg viewBox="0 0 64 64" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" style="display:block;">
      <rect x="5" y="24" width="30" height="18" rx="3"/>
      <rect x="11" y="28" width="8" height="7"/>
      <rect x="23" y="28" width="8" height="7"/>
      <circle cx="13" cy="46" r="3.5"/>
      <circle cx="27" cy="46" r="3.5"/>
      <line x1="5" y1="24" x2="5" y2="18"/>
      <line x1="5" y1="18" x2="13" y2="18"/>
      <circle cx="49" cy="18" r="7"/>
      <circle cx="49" cy="18" r="2.3" fill="currentColor" stroke="none"/>
      <line x1="49" y1="7" x2="49" y2="11"/>
      <line x1="49" y1="25" x2="49" y2="29"/>
      <line x1="38" y1="18" x2="42" y2="18"/>
      <line x1="56" y1="18" x2="60" y2="18"/>
      <line x1="40.7" y1="9.7" x2="43.5" y2="12.5"/>
      <line x1="54.5" y1="23.5" x2="57.3" y2="26.3"/>
      <line x1="40.7" y1="26.3" x2="43.5" y2="23.5"/>
      <line x1="54.5" y1="12.5" x2="57.3" y2="9.7"/>
    </svg>`;

    function addStyles() {
        if (document.getElementById('train-custom-styles')) return;
        const style = document.createElement('style');
        style.id = 'train-custom-styles';
        style.innerHTML = `
            #train-settings-launcher {
                display: inline-flex; align-items: center; justify-content: center;
                width: 30px; height: 30px; box-sizing: border-box;
                background-color: rgba(60,60,60,0.85); color: #ddd;
                border: 1px solid rgba(255,255,255,0.25); border-radius: 6px;
                cursor: pointer; padding: 0; line-height: 0; margin-left: 6px;
            }
            #train-settings-launcher:hover { background-color: rgba(90,90,90,0.9); color:#fff; }
            /* Fallback pozíció, ha nem sikerül a Gym cím mellé illeszteni */
            #train-settings-launcher.train-launcher-fallback {
                position: fixed;
                right: max(12px, env(safe-area-inset-right));
                bottom: max(12px, env(safe-area-inset-bottom));
                z-index: 99999;
                box-shadow: 0 2px 6px rgba(0,0,0,0.5);
            }
            #train-modal-overlay {
                display: none; position: fixed; top: 0; left: 0;
                width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 100000;
            }
            #train-settings-modal {
                position: fixed; top: 50%; left: 50%;
                transform: translate(-50%, -50%);
                background: #fff; color: #333; border-radius: 10px; padding: 16px;
                width: min(380px, 92vw);
                max-height: 85vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
                box-sizing: border-box;
                box-shadow: 0 5px 15px rgba(0,0,0,0.7); font-family: Arial, sans-serif;
            }
            #train-settings-modal h3 { margin: 0 0 15px 0; text-align: center; border-bottom: 2px solid #ddd; padding-bottom: 10px; }
            #train-preview-wrapper { display: flex; justify-content: center; align-items: center; background: #f4f4f4; border: 1px solid #ddd; border-radius: 6px; padding: 10px; margin-bottom: 15px; }
            #train-preview svg { width: 120px; height: 72px; max-width: 100%; }
            .train-radio-group {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
                gap: 8px; margin-bottom: 15px;
            }
            .train-radio-group label { display: flex; align-items: center; cursor: pointer; font-size: 12px; }
            .train-radio-group input { margin-right: 5px; cursor: pointer; }
            .train-color-group { margin-bottom: 20px; }
            .train-color-group label { display: block; font-weight: bold; margin-bottom: 5px; }
            .train-color-row { display: flex; gap: 8px; }
            #train-color-picker { flex: 1; height: 40px; cursor: pointer; border: 1px solid #ccc; border-radius: 4px; min-width: 0; }
            #train-reset-color-btn { flex: 0 0 auto; background-color: #7f8c8d; color: #fff; border: none; border-radius: 4px; padding: 0 12px; cursor: pointer; font-weight: bold; font-size: 12px; }
            #train-reset-color-btn:hover { background-color: #95a5a6; }
            .train-modal-buttons { display: flex; gap: 10px; }
            .train-btn { flex: 1; padding: 10px; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; color: #fff; }
            #train-save-btn { background-color: #27ae60; }
            #train-save-btn:hover { background-color: #2ecc71; }
            #train-cancel-btn { background-color: #c0392b; }
            #train-cancel-btn:hover { background-color: #e74c3c; }
            .train-icon-btn { transition: transform 0.1s ease-in-out, filter 0.1s ease-in-out; cursor: pointer; display: block; margin: 0 auto; overflow: visible; }
            .train-icon-btn:hover { transform: scale(1.15); filter: brightness(1.1); }
            .train-icon-btn:active { transform: scale(0.95); }
            .custom-train-wrapper { display: inline-flex; justify-content: center; align-items: center; width: 100%; height: 100%; }
            .custom-train-wrapper.train-disabled .train-icon-btn:hover { transform: none; filter: grayscale(1) brightness(0.85); }
            .custom-train-wrapper.train-disabled .train-icon-btn:active { transform: none; }
            .custom-train-wrapper.train-disabled { cursor: not-allowed; }
            @media (max-width: 420px) {
                #train-settings-modal { padding: 12px; }
                .train-radio-group { grid-template-columns: repeat(auto-fit, minmax(76px, 1fr)); font-size: 11px; }
            }
        `;
        document.head.appendChild(style);
    }

    function updatePreview() {
        const checked = document.querySelector('input[name="trainType"]:checked');
        const type = checked ? checked.value : settings.trainType;
        const color = document.getElementById('train-color-picker').value;
        const preview = document.getElementById('train-preview');
        if (preview) {
            preview.innerHTML = (trainIcons[type] || trainIcons.train1).replace(/COLOR_PLACEHOLDER/g, color);
        }
    }

    function buildRadioGroup() {
        let html = '';
        for (let i = 1; i <= 16; i++) {
            const type = 'train' + i;
            html += `<label><input type="radio" name="trainType" value="${type}" ${settings.trainType === type ? 'checked' : ''}> Train ${i}</label>`;
        }
        return html;
    }

    // Megpróbáljuk a Gym cím / City-tutorial gombok mellé illeszteni a launcher-t.
    // A Torn oldal DOM-ja időnként változik, ezért több lehetséges helyet is megnézünk,
    // és ha egyik sem található, marad a mobil-biztos, sarokba rögzített változat.
    function tryAttachToTitleBar(launcher) {
        const containerSelectors = [
            '.tutorial-button-icon',
            '[class*="titleButtons"]',
            '[class*="topButtons"]',
            '[class*="content-title"] [class*="right"]',
            '[class*="titleWrapper"] [class*="buttons"]'
        ];

        for (const sel of containerSelectors) {
            const container = document.querySelector(sel);
            if (container && container.parentElement) {
                container.parentElement.insertBefore(launcher, container);
                return true;
            }
        }

        // Fallback: keresünk egy elemet, aminek pontosan "Gym" a szövege (a cím maga)
        const candidates = document.querySelectorAll('div, span, h1, h2, h3, h4, h5');
        for (const el of candidates) {
            if (el.children.length === 0 && el.textContent.trim() === 'Gym') {
                el.insertAdjacentElement('afterend', launcher);
                return true;
            }
        }

        return false;
    }

    function createUI() {
        if (!document.body || document.getElementById('train-settings-launcher')) return;

        addStyles();

        const launcher = document.createElement('button');
        launcher.id = 'train-settings-launcher';
        launcher.type = 'button';
        launcher.title = 'Train button settings';
        launcher.setAttribute('aria-label', 'Train button settings');
        launcher.innerHTML = settingsIconSvg;

        const attached = tryAttachToTitleBar(launcher);
        if (!attached) {
            launcher.classList.add('train-launcher-fallback');
            document.body.appendChild(launcher);
        }

        const overlay = document.createElement('div');
        overlay.id = 'train-modal-overlay';

        const modal = document.createElement('div');
        modal.id = 'train-settings-modal';
        modal.innerHTML = `
            <h3>Train Settings</h3>
            <div id="train-preview-wrapper"><div id="train-preview"></div></div>
            <div class="train-radio-group">${buildRadioGroup()}</div>
            <div class="train-color-group">
                <label for="train-color-picker">Main Color:</label>
                <div class="train-color-row">
                    <input type="color" id="train-color-picker" value="${settings.trainColors[settings.trainType] || trainDefaultColors[settings.trainType] || '#F1C40F'}">
                    <button id="train-reset-color-btn" type="button">Reset to Default</button>
                </div>
            </div>
            <div class="train-modal-buttons">
                <button id="train-save-btn" class="train-btn">Save</button>
                <button id="train-cancel-btn" class="train-btn">Cancel</button>
            </div>
        `;
        overlay.appendChild(modal);
        document.body.appendChild(overlay);

        function openModal() {
            overlay.style.display = 'block';
            if (!trainIcons[settings.trainType]) {
                settings.trainType = 'train1';
                GM_setValue('trainType', 'train1');
            }
            const radio = document.querySelector(`input[name="trainType"][value="${settings.trainType}"]`);
            if (radio) radio.checked = true;
            document.getElementById('train-color-picker').value = settings.trainColors[settings.trainType] || trainDefaultColors[settings.trainType] || '#F1C40F';
            updatePreview();
        }

        function closeModal() {
            overlay.style.display = 'none';
        }

        launcher.addEventListener('click', openModal);
        document.getElementById('train-cancel-btn').addEventListener('click', closeModal);
        overlay.addEventListener('click', (e) => { if (e.target === overlay) closeModal(); });

        modal.querySelectorAll('input[name="trainType"]').forEach((input) => {
            input.addEventListener('change', () => {
                const type = input.value;
                document.getElementById('train-color-picker').value = settings.trainColors[type] || trainDefaultColors[type] || '#F1C40F';
                updatePreview();
            });
        });

        document.getElementById('train-color-picker').addEventListener('input', updatePreview);

        document.getElementById('train-reset-color-btn').addEventListener('click', () => {
            const checked = document.querySelector('input[name="trainType"]:checked');
            const type = checked ? checked.value : settings.trainType;
            document.getElementById('train-color-picker').value = trainDefaultColors[type] || '#F1C40F';
            updatePreview();
        });

        document.getElementById('train-save-btn').addEventListener('click', () => {
            const selectedTrain = document.querySelector('input[name="trainType"]:checked').value;
            const selectedColor = document.getElementById('train-color-picker').value;

            settings.trainColors[selectedTrain] = selectedColor;
            settings.trainType = selectedTrain;

            GM_setValue('trainType', selectedTrain);
            GM_setValue('trainColors', JSON.stringify(settings.trainColors));

            closeModal();

            document.querySelectorAll('.custom-train-wrapper').forEach((wrapper) => {
                wrapper.innerHTML = getIconHtml();
            });
        });

        if (typeof GM_registerMenuCommand !== 'undefined') {
            GM_registerMenuCommand('Open Train Button Settings', openModal);
        }
    }

    function getIconHtml() {
        const safeTrainType = trainIcons[settings.trainType] ? settings.trainType : 'train1';
        const color = settings.trainColors[safeTrainType] || trainDefaultColors[safeTrainType] || '#F1C40F';
        return trainIcons[safeTrainType].replace(/COLOR_PLACEHOLDER/g, color);
    }

    function isDisabled(el) {
        if (!el) return false;
        if (el.disabled) return true;
        if (el.getAttribute('aria-disabled') === 'true') return true;
        if (el.classList && el.classList.contains('disabled')) return true;
        if (typeof el.className === 'string' && el.className.toLowerCase().indexOf('disabled') !== -1) return true;
        return false;
    }

    function updateDisabledStates() {
        document.querySelectorAll('[data-train-replaced="true"]').forEach((el) => {
            const wrapper = el.querySelector('.custom-train-wrapper');
            if (!wrapper) return;
            if (isDisabled(el)) {
                wrapper.classList.add('train-disabled');
            } else {
                wrapper.classList.remove('train-disabled');
            }
        });
    }

    function replaceTrainButtons() {
        if (!document.body) return;
        createUI();

        const elements = document.querySelectorAll('button, a, [class*="btn"]');

        elements.forEach((el) => {
            if (el.textContent.trim().toUpperCase() === 'TRAIN' && !el.dataset.trainReplaced) {
                if (el.querySelectorAll('input, select, textarea').length > 0) return;

                el.dataset.trainReplaced = 'true';
                el.style.color = 'transparent';
                el.style.fontSize = '0px';
                el.style.backgroundColor = 'transparent';
                el.style.backgroundImage = 'none';
                el.style.border = 'none';
                el.style.boxShadow = 'none';
                el.style.padding = '0';
                el.setAttribute('aria-label', 'Train');

                const iconWrapper = document.createElement('span');
                iconWrapper.className = 'custom-train-wrapper';
                iconWrapper.title = 'Train';
                iconWrapper.innerHTML = getIconHtml();
                if (isDisabled(el)) {
                    iconWrapper.classList.add('train-disabled');
                }

                // Minden egyes kattintás pontosan egyszer szólaltatja meg a közös hangot,
                // így ha valaki többször nyom rá, annyiszor is hallható lesz.
                iconWrapper.addEventListener('click', () => {
                    if (isDisabled(el)) return;
                    playTrainSound();
                });

                el.appendChild(iconWrapper);
            }
        });

        updateDisabledStates();
    }

    let scanScheduled = false;
    function scheduleScan() {
        if (scanScheduled) return;
        scanScheduled = true;
        setTimeout(() => {
            scanScheduled = false;
            replaceTrainButtons();
        }, 150);
    }

    function startObserving() {
        if (!document.body) {
            setTimeout(startObserving, 100);
            return;
        }
        const observer = new MutationObserver(() => scheduleScan());
        observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'disabled', 'aria-disabled'] });
        replaceTrainButtons();
    }

    startObserving();
    setInterval(replaceTrainButtons, 2000);

})();