Проблема: анимация выигрышная колеса (не сектора) с градиентами работает в TWA телеграм web app с ПК, MAC, Android, а на Iphone в приложении телеграм она неверно отображается, квадратная. Градиент сам верен, но элемент этот квадратный просто

---

style.css:

/* Сброс стилей и базовые настройки */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
}

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: var(--tg-theme-bg-color, #0f0f1e);
    color: var(--tg-theme-text-color, #ffffff);
    position: relative;
}

/* Переменные для Telegram тем */
:root {
    --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    --gold-gradient: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
    /* Увеличение размера колеса в 1.25 раза */
    --wheel-size: min(300px, 50.75vw);
    --safe-area-top: env(safe-area-inset-top, 20px);
    --safe-area-bottom: env(safe-area-inset-bottom, 20px);
}

/* Основная обертка */
.app-wrapper {
    width: 100%;
    height: 100%;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    background-image: url('../static/background.png');
    background-size: 100% 100%;
    /* ИЗМЕНЕНИЕ: Заменяем background-position */
    background-position: center bottom; /* Было: center */
    background-repeat: no-repeat;
}

/* Фоновые эффекты */
.background-effects {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    pointer-events: none;
}
.gradient-orb { position: absolute; border-radius: 50%; filter: blur(80px); opacity: 0.2; }
.orb-1 { width: 350px; height: 350px; background: radial-gradient(circle, #667eea 0%, transparent 70%); top: -150px; left: -150px; animation: float-1 20s infinite ease-in-out; }
.orb-2 { width: 300px; height: 300px; background: radial-gradient(circle, #f093fb 0%, transparent 70%); bottom: -150px; right: -150px; animation: float-2 25s infinite ease-in-out; }
.orb-3 { width: 250px; height: 250px; background: radial-gradient(circle, #4facfe 0%, transparent 70%); top: 50%; left: 50%; transform: translate(-50%, -50%); animation: float-3 30s infinite ease-in-out; }
@keyframes float-1 { 0%, 100% { transform: translate(0, 0) rotate(0deg); } 33% { transform: translate(40px, -40px) rotate(120deg); } 66% { transform: translate(-30px, 30px) rotate(240deg); } }
@keyframes float-2 { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(-40px, -40px) scale(1.1); } }
@keyframes float-3 { 0%, 100% { transform: translate(-50%, -50%) scale(1); } 50% { transform: translate(-50%, -50%) scale(0.9); } }

/* Основной контент */
.main-content {
    width: 100%;
    max-width: 480px; /* Keep max-width for overall layout */
    height: 100%;
    padding: var(--safe-area-top) 20px var(--safe-area-bottom);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-evenly;
    position: relative;
    z-index: 1;
}

/* Заголовок */
.app-header { text-align: center; margin-bottom: 0; 
    margin-top: 40px;
}
.app-title { font-size: 36px; font-weight: 800; background: var(--gold-gradient); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; text-shadow: 0 2px 10px rgba(255, 215, 0, 0.3); margin-top: 20px; }
.app-tagline { font-size: 16px; color: var(--tg-theme-hint-color, #aaa); }

/* Секция колеса */
.wheel-section {
    position: absolute; /* Абсолютное позиционирование */
    width: var(--wheel-size); /* Размер определяется переменной */
    height: var(--wheel-size);
    margin: 0; /* Убираем автоматические отступы */
    /* Примерное позиционирование на основе фонового изображения */
    left: 50%; /* Остается по центру горизонтали */
    bottom: 160px; 

    /* Убираем вертикальное центрирование из transform, оставляем только горизонтальное и масштабирование */
    transform: translateX(-50%) scale(0.81); /* Было: translate(-50%, -50%) scale(0.81); */
    
    /* transform-origin больше не нужен, но можно оставить для ясности */
    transform-origin: center center;
}
/* Декорация колеса */
.wheel-decoration { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); 
    /* Увеличение отступа декорации в 1.25 раза */
    width: calc(100% + 37.5px); 
    height: calc(100% + 37.5px); 
    pointer-events: none; 
}

/* ИЗМЕНЕНИЕ: Обновленный стиль борта колеса для придания объема и глянца */
.outer-ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: radial-gradient(circle at 50% 30%, #7b68ee, #3b2f8a 80%);
    box-shadow: inset 0 6px 12px rgba(255, 255, 255, 0.1), 
                inset 0 -6px 12px rgba(0, 0, 0, 0.3);
}

.outer-ring::after { content: ''; position: absolute; 
    /* Увеличение внутреннего отступа в 1.25 раза */
    inset: 0; 
    border-radius: 50%; background: var(--tg-theme-bg-color, #0f0f1e); 
}
@keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.inner-glow { position: absolute; 
    /* Увеличение отступа свечения в 1.25 раза */
    inset: -25px; 
    border-radius: 50%; background: radial-gradient(circle, rgba(255, 215, 0, 0.1) 0%, transparent 70%); animation: pulse 2s infinite ease-in-out; 
}
@keyframes pulse { 0%, 100% { transform: scale(1); opacity: 0.5; } 50% { transform: scale(1.25); opacity: 0.1; } }

/* ИЗМЕНЕНИЕ: Указатель возвращен наверх и развернут */
.wheel-pointer {
    position: absolute;
    /* Увеличение отступа сверху в 1.25 раза */
    top: -50px; 
    left: 51%;
    /* Разворот на 180 градусов для направления вниз */
    transform: translateX(-50%) rotate(180deg); 
    z-index: 10;
    /* Увеличение тени в 1.25 раза */
    filter: drop-shadow(0 5px 10px rgba(0, 0, 0, 0.3)); 
    animation: pointer-bounce 2s infinite ease-in-out;
}

/* ИЗМЕНЕНИЕ: Анимация отскока скорректирована для развернутой стрелки */
@keyframes pointer-bounce {
    0%, 100% {
        transform: translateX(-50%) rotate(180deg) translateY(0);
    }
    50% {
        /* Увеличение смещения в 1.25 раза */
        transform: translateX(-50%) rotate(180deg) translateY(6.25px);
    }
}

/* Контейнер колеса */
.wheel-wrapper { 
    position: relative; 
    width: 100%; 
    height: 100%; 
    filter: drop-shadow(0 31.25px 62.5px rgba(0, 0, 0, 0.3)); 
}

#canvas {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.05), inset 0 0 35px rgba(0,0,0,0.3);
    transition: filter 0.3s ease, transform 0.3s ease;
    will-change: filter, transform;
    -webkit-transform: translate3d(0,0,0);
    transform: translate3d(0,0,0);
    -webkit-perspective: 1000;
    perspective: 1000;
}

/* Класс для свечения canvas во время анимации победителя */
.winner-glow {
    animation: epicWinnerGlow 3s ease-in-out;
}

@keyframes epicWinnerGlow {
    0% {
        filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.8)) 
                drop-shadow(0 0 40px rgba(255, 215, 0, 0.6));
        transform: scale(1);
    }
    10% {
        filter: drop-shadow(0 0 60px rgba(255, 255, 255, 1)) 
                drop-shadow(0 0 80px rgba(255, 215, 0, 0.9))
                drop-shadow(0 0 100px rgba(255, 165, 0, 0.7));
        transform: scale(1.05);
    }
    25% {
        filter: drop-shadow(0 0 40px rgba(255, 255, 255, 0.9)) 
                drop-shadow(0 0 60px rgba(255, 215, 0, 0.8))
                drop-shadow(0 0 80px rgba(255, 20, 147, 0.6));
        transform: scale(1.02);
    }
    50% {
        filter: drop-shadow(0 0 50px rgba(255, 255, 255, 1)) 
                drop-shadow(0 0 70px rgba(255, 215, 0, 0.9))
                drop-shadow(0 0 90px rgba(0, 255, 255, 0.7));
        transform: scale(1.03);
    }
    75% {
        filter: drop-shadow(0 0 35px rgba(255, 255, 255, 0.8)) 
                drop-shadow(0 0 55px rgba(255, 215, 0, 0.7))
                drop-shadow(0 0 75px rgba(255, 105, 180, 0.5));
        transform: scale(1.01);
    }
    100% {
        filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.5))
                drop-shadow(0 0 25px rgba(255, 215, 0, 0.3));
        transform: scale(1);
    }
}

.wheel-wrapper {
    overflow: visible;
    position: relative;
}

.wheel-wrapper canvas {
    position: relative;
    z-index: 0;
}

/* Дополнительные эффекты для контейнера */
.wheel-wrapper::before {
    content: '';
    position: absolute;
    top: -20px;
    left: -20px;
    right: -20px;
    bottom: -20px;
    border-radius: 50%;
    background: radial-gradient(circle, transparent 60%, rgba(255, 255, 255, 0.1) 70%, transparent 80%);
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
    z-index: 0;
}

.wheel-wrapper.winner-glow::before {
    animation: outerRingGlow 3s ease-in-out;
}

@keyframes outerRingGlow {
    0%, 100% { opacity: 0; }
    20%, 80% { opacity: 1; }
    50% { opacity: 0.7; }
}

/* Эффект пульсации для всего контейнера */
.wheel-wrapper.winner-glow {
    animation: containerPulse 3s ease-in-out;
}

@keyframes containerPulse {
    0%, 100% { 
        filter: drop-shadow(0 31.25px 62.5px rgba(0, 0, 0, 0.3)); 
    }
    25% { 
        filter: drop-shadow(0 31.25px 62.5px rgba(0, 0, 0, 0.3))
                drop-shadow(0 0 50px rgba(255, 215, 0, 0.4)); 
    }
    50% { 
        filter: drop-shadow(0 31.25px 62.5px rgba(0, 0, 0, 0.3))
                drop-shadow(0 0 70px rgba(255, 215, 0, 0.6))
                drop-shadow(0 0 100px rgba(255, 255, 255, 0.3)); 
    }
    75% { 
        filter: drop-shadow(0 31.25px 62.5px rgba(0, 0, 0, 0.3))
                drop-shadow(0 0 50px rgba(255, 215, 0, 0.4)); 
    }
}

/* Анимация для текста на кнопке во время победы */
.spin-button.winner-celebration .button-text {
    animation: textCelebration 3s ease-in-out;
}

@keyframes textCelebration {
    0%, 100% { 
        transform: scale(1);
        color: inherit;
    }
    25% { 
        transform: scale(1.1);
        color: #FFD700;
        text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);
    }
    50% { 
        transform: scale(1.05);
        color: #FFFFFF;
        text-shadow: 0 0 15px rgba(255, 255, 255, 0.9);
    }
    75% { 
        transform: scale(1.08);
        color: #FF6B6B;
        text-shadow: 0 0 12px rgba(255, 107, 107, 0.7);
    }
}

/* Эффект для статистики во время победы */
.stats.winner-celebration {
    animation: statsGlow 3s ease-in-out;
}

@keyframes statsGlow {
    0%, 100% { 
        filter: none;
        transform: scale(1);
    }
    25% { 
        filter: drop-shadow(0 0 10px rgba(255, 215, 0, 0.6));
        transform: scale(1.02);
    }
    50% { 
        filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.8));
        transform: scale(1.03);
    }
    75% { 
        filter: drop-shadow(0 0 12px rgba(255, 107, 107, 0.5));
        transform: scale(1.01);
    }
}

/* Эффект для всего экрана */
.main-content.winner-celebration {
    animation: screenFlash 3s ease-in-out;
}

@keyframes screenFlash {
    0%, 100% { 
        background: inherit;
    }
    5% { 
        background: radial-gradient(circle at center, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
    }
    15% { 
        background: radial-gradient(circle at center, rgba(255, 215, 0, 0.05) 0%, transparent 70%);
    }
}

/* Центральная кнопка SPIN */
.center-spin-button { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); 
    /* Увеличение размера кнопки в 1.25 раза */
    width: 140px; 
    height: 140px; 
    border: none; border-radius: 50%; background: var(--primary-gradient); cursor: pointer; overflow: hidden; transition: all 0.3s ease; 
    /* Увеличение тени в 1.25 раза */
    box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.2), 0 10px 25px rgba(102, 126, 234, 0.5), inset 0 -5px 15px rgba(0, 0, 0, 0.2); 
}

/* Новая анимация пульсации для активной кнопки */
.center-spin-button:not(:disabled) {
    animation: button-pulse-animation 2s infinite ease-in-out;
}

@keyframes button-pulse-animation {
    0%, 100% {
        transform: translate(-50%, -50%) scale(1);
        box-shadow: 0 0 0 5px rgba(102, 126, 234, 0.2), 0 10px 25px rgba(102, 126, 234, 0.4);
    }
    50% {
        transform: translate(-50%, -50%) scale(1.05);
        box-shadow: 0 0 0 10px rgba(102, 126, 234, 0.4), 0 15px 35px rgba(102, 126, 234, 0.5);
    }
}

.button-inner { position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
.button-text { 
    /* Увеличение размера текста в 1.25 раза */
    font-size: 32px; 
    font-weight: 800; color: #fff; letter-spacing: 1.5px; z-index: 2; 
    /* Увеличение тени текста в 1.25 раза */
    text-shadow: 0 2.5px 5px rgba(0, 0, 0, 0.3); 
}
.button-shine { position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: linear-gradient(45deg, transparent 30%, rgba(255, 255, 255, 0.3) 50%, transparent 70%); transform: rotate(45deg); transition: all 0.6s; opacity: 0; }
.center-spin-button:not(:disabled):hover { transform: translate(-50%, -50%) scale(1.05); 
    /* Увеличение тени в 1.25 раза */
    box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.3), 0 12.5px 37.5px rgba(102, 126, 234, 0.6), inset 0 -5px 15px rgba(0, 0, 0, 0.2); 
}
.center-spin-button:not(:disabled):hover .button-shine { opacity: 1; transform: rotate(45deg) translateY(100%); }
.center-spin-button:not(:disabled):active { transform: translate(-50%, -50%) scale(0.95); }
.center-spin-button:disabled { background: linear-gradient(135deg, #555 0%, #333 100%); cursor: not-allowed; 
    /* Увеличение тени в 1.25 раза */
    box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.05), inset 0 -3.75px 12.5px rgba(0, 0, 0, 0.2); 
}
.center-spin-button.spinning { animation: spin-pulse 1s infinite ease-in-out; }
@keyframes spin-pulse { 
    0%, 100% { 
        transform: translate(-50%, -50%) scale(1); 
        /* Увеличение тени в 1.25 раза */
        box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.2), 0 10px 25px rgba(102, 126, 234, 0.5); 
    } 
    50% { 
        transform: translate(-50%, -50%) scale(1.1); 
        /* Увеличение тени в 1.25 раза */
        box-shadow: 0 0 0 10px rgba(255, 215, 0, 0.4), 0 15px 37.5px rgba(255, 215, 0, 0.6); 
    } 
}

/* Остальные стили без изменений */
.wheel-lights { position: absolute; 
    /* Увеличение отступа огней в 1.25 раза */
    inset: -37.5px; 
    pointer-events: none; 
}
.light { position: absolute; 
    /* Увеличение размера огней в 1.25 раза */
    width: 10px; 
    height: 10px; 
    background: #FFD700; border-radius: 50%; 
    /* Увеличение свечения огней в 1.25 раза */
    box-shadow: 0 0 12.5px #FFD700; 
    opacity: 0; animation: light-twinkle 3s infinite ease-in-out; 
}
.light-1 { top: 505%; left: 50%; animation-delay: 0s; }
.light-2 { top: 50%; right: 5%; animation-delay: 0.75s; }
.light-3 { bottom: 5%; left: 50%; animation-delay: 1.5s; }
.light-4 { top: 50%; left: 5%; animation-delay: 2.25s; }
@keyframes light-twinkle { 0%, 100% { opacity: 0; transform: scale(0.5); } 50% { opacity: 1; transform: scale(1.2); } }

/* Увеличение размеров и отступов панели статистики в 1.25 раза */
.stats-panel {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 25px;
    padding: 20px 37.5px;
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(20px);
    border-radius: 25px;
    border: 1.25px solid rgba(255, 255, 255, 0.1);
    /* Удаляем предыдущий margin-top и добавляем auto */
    margin-top: auto;
    margin-bottom: 20px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1), inset 0 1.25px 0 rgba(255, 255, 255, 0.1);
}
.stat-card { display: flex; align-items: center; 
    gap: 15px; 
}
.stat-icon { 
    font-size: 35px; 
    filter: drop-shadow(0 2.5px 5px rgba(0, 0, 0, 0.2)); 
}
.stat-info { display: flex; flex-direction: column; align-items: center; }
.stat-value { 
    font-size: 27.5px; 
    font-weight: 800; color: #fff; line-height: 1; 
    text-shadow: 0 2.5px 5px rgba(0, 0, 0, 0.3); 
}
.stat-label { 
    font-size: 15px; 
    color: var(--tg-theme-hint-color, #888); text-transform: uppercase; letter-spacing: 0.5px; 
    margin-top: 5px; 
}
.stat-divider { 
    width: 1.25px; 
    height: 50px; 
    background: linear-gradient( to bottom, transparent, rgba(255, 255, 255, 0.2), transparent ); 
}
.win-effects { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1000; }
.confetti-piece { position: absolute; width: 8px; height: 8px; background: #FFD700; animation: confetti-fall 3s linear forwards; }
@keyframes confetti-fall { 0% { transform: translateY(-100vh) rotate(0deg); opacity: 1; } 100% { transform: translateY(100vh) rotate(720deg); opacity: 0; } }

/* Адаптивные стили также увеличены в 1.25 раза */
@media (max-height: 800px) { 
    :root { --wheel-size: min(450px, 106.25vw); } 
    .center-spin-button { width: 112.5px; height: 112.5px; } 
    .button-text { font-size: 27.5px; } 
    .app-title { font-size: 40px; } 
}
@media (max-height: 700px) { 
    :root { --wheel-size: min(375px, 100vw); } 
    .center-spin-button { width: 100px; height: 100px; } 
    .button-text { font-size: 25px; } 
    .app-title { font-size: 35px; } 
    .stats-panel { padding: 15px 25px; } 
}
@media (max-width: 380px) { 
    .main-content { padding-left: 18.75px; padding-right: 18.75px; } 
    .stats-panel { gap: 18.75px; padding: 15px 20px; } 
    .stat-card { gap: 10px; } 
    .stat-icon { font-size: 30px; } 
    .stat-value { font-size: 25px; } 
}

---

script:js:

// D:/python projects/seobot_renewed_9_11/seobot/bot\web_app\js\script.js

// D:/python projects/seobot_renewed_9_11/seobot/bot\web_app\js\script.js

const tg = window.Telegram.WebApp;
const BACKEND_URL = 'https://cloudyspin.ddns.net';

// Элементы DOM
const spinButton = document.getElementById('spin-button');
const spinsCountEl = document.getElementById('spins-count');
const pointsCountEl = document.getElementById('points-count');
const mainContent = document.querySelector('.main-content');
const wheelWrapper = document.querySelector('.wheel-wrapper');
const spinButtonText = spinButton.querySelector('.button-text');
const spinsLabelEl = document.querySelector('#spins-count + .stat-label');
const pointsLabelEl = document.querySelector('#points-count + .stat-label');
const ANIMATION_DURATION_S = 6;

let theWheel;
let wheelSpinning = false;
let currentUserInfo = { available_spins: 0, loyalty_points: 0 };
let wheelConfig = {}; // Храним здесь полную конфигурацию, включая призы
let i18n = {};


// --- ИНИЦИАЛИЗАЦИЯ ---
tg.ready();
main();

async function main() {
    tg.expand();
    mainContent.style.opacity = 1;

    try {
        wheelConfig = await apiFetch('/api/v1/wheel-config');
        i18n = wheelConfig.ui_localization || {};
        applyLocalization();

        if (wheelConfig && wheelConfig.prizes) {
            createWheel(wheelConfig.prizes);
        } else {
            tg.showAlert(i18n.alert_config_error || 'Could not load wheel configuration.');
        }
        await loadUserInfo();
    } catch (error) {
        console.error("Initialization failed:", error);
        const errorMessage = i18n.alert_generic_error 
            ? i18n.alert_generic_error.replace('{error_message}', error.message) 
            : `Failed to load data: ${error.message}`;
        tg.showAlert(errorMessage);
    }
}

function applyLocalization() {
    document.title = i18n.title || 'CloudySpin';
    spinsLabelEl.textContent = i18n.spins_label || 'spins';
    pointsLabelEl.textContent = i18n.points_label || 'points';
    updateSpinButtonText();
}

function updateSpinButtonText() {
    if (wheelSpinning) {
        spinButtonText.textContent = i18n.spin_button_spinning || "SPINNING";
    } else {
        spinButtonText.textContent = currentUserInfo.available_spins > 0 
            ? (i18n.spin_button_ready || "SPIN") 
            : (i18n.spin_button_no_spins || "0");
    }
}

function createWheel(prizes) {
    if (theWheel) {
        theWheel.stopAnimation(false);
        theWheel = null;
    }

    const canvas = document.getElementById('canvas');
    if (!canvas) return;

    const rarityStyles = {
        common:    { base: '#B0BEC5', accent: '#ECEFF1', text: '#000000' }, // Черный текст
        rare:      { base: '#5C6BC0', accent: '#9FA8DA', text: '#FFFFFF' }, // Белый текст
        epic:      { base: '#5C6BC0', accent: '#9FA8DA', text: '#FFFFFF' }, // Белый текст
        legendary: { base: '#FFA000', accent: '#FFD54F', text: '#000000' }, // Черный текст
        mythic:    { base: '#00ACC1', accent: '#80DEEA', text: '#000000' }  // Черный текст
    };

    const segmentsData = [];
    let colorAlternator = 0;
    let hasPremiumPrize = false;

    prizes.forEach(prize => {
        let style = rarityStyles[prize.rarity] || rarityStyles.common;
        
        if (['common', 'rare', 'epic'].includes(prize.rarity)) {
            style = colorAlternator % 2 === 0 ? rarityStyles.common : rarityStyles.rare;
            colorAlternator++;
        } else {
            hasPremiumPrize = true;
        }

        const gradient = canvas.getContext('2d').createRadialGradient(210, 210, 10, 210, 210, 210);
        gradient.addColorStop(0, style.accent);
        gradient.addColorStop(1, style.base);

        segmentsData.push({
            'fillStyle': gradient,
            'text': prize.localized_name,
            'id': prize.id,
            'textFillStyle': style.text,
            'textFontWeight': 'bold' // Делаем весь текст жирным
        });
    });
    
    canvas.classList.toggle('premium-glow', hasPremiumPrize);

    theWheel = new Winwheel({
        'canvasId': 'canvas',
        'numSegments': segmentsData.length,
        'outerRadius': 208,
        'innerRadius': 30,
        'segments': segmentsData,
        'textFontSize': 12, // Немного уменьшим для лучшего вписывания
        'strokeStyle': 'rgba(0,0,0,0.2)',
        'lineWidth': 3,
        // --- ВАШ ФИКС ОРИЕНТАЦИИ ТЕКСТА ---
        'textOrientation': 'horizontal',
        'textDirection': 'normal',
        'textAlignment': 'center', // Центрируем текст по радиусу
        'textMargin': 10,
        // --- КОНЕЦ ФИКСА ---
        'animation': {
            'type': 'spinToStop',
            'duration': ANIMATION_DURATION_S,
            'spins': 12,
            'easing': 'Power4.easeOut',
            // <<< ИЗМЕНЕНИЕ: Callback теперь вызывает ТОЛЬКО визуальную функцию >>>
            'callbackFinished': () => {},
            'callbackAfter': () => {}
        }
    });
}

function animateWinnerSegment() {
    const winningSegment = theWheel.getIndicatedSegment();
    if (!winningSegment) return;

    const canvas = document.getElementById('canvas');
    const wheelWrapper = document.querySelector('.wheel-wrapper');
    const ctx = canvas.getContext('2d');
    
    // Helper functions hexToRgb, extractSegmentColor, createSegmentGradient are removed as per instructions.
    // The segmentColor variable is also no longer needed.
    
    // Добавляем классы ко всем элементам для полного эффекта
    canvas.classList.add('winner-glow');
    wheelWrapper.classList.add('winner-glow');
    spinButton?.classList.add('winner-celebration');
    document.querySelector('.stats')?.classList.add('winner-celebration');
    mainContent?.classList.add('winner-celebration');
    
    // Сохраняем оригинальные стили
    const originalFillStyle = winningSegment.fillStyle;
    const originalStrokeStyle = theWheel.strokeStyle;
    const originalLineWidth = theWheel.lineWidth;
    
    // Параметры анимации
    let animationTime = 0;
    const animationDuration = 3000;
    const fps = 60;
    const frameTime = 1000 / fps;
    
    // Создаем частицы для эффекта конфетти
    const particles = [];
    for (let i = 0; i < 40; i++) {
        particles.push({
            x: canvas.width / 2 + (Math.random() - 0.5) * 100,
            y: canvas.height / 2 + (Math.random() - 0.5) * 100,
            vx: (Math.random() - 0.5) * 12,
            vy: (Math.random() - 0.5) * 12 - 2, // Начальная скорость вверх
            life: 1,
            decay: 0.015 + Math.random() * 0.02,
            size: 3 + Math.random() * 5,
            color: ['#FFD700', '#FFFFFF', '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'][Math.floor(Math.random() * 6)],
            rotation: Math.random() * Math.PI * 2,
            rotationSpeed: (Math.random() - 0.5) * 0.3,
            type: Math.random() > 0.5 ? 'star' : 'circle'
        });
    }
    
    // Улучшенная функция "дыхания" для свечения
    function breathingEffect(time) {
        const progress = time / animationDuration;
        const mainWave = Math.sin(progress * Math.PI * 4);
        const subWave = Math.sin(progress * Math.PI * 8) * 0.3;
        const pulseWave = Math.sin(progress * Math.PI * 16) * 0.15; // Быстрые микропульсации
        const fadeOut = 1 - Math.pow(progress, 2); // Квадратичное затухание
        return Math.abs(mainWave + subWave + pulseWave) * fadeOut;
    }
    
    // Функция масштабирования сегмента с эффектом "взрыва"
    function scaleEffect(time) {
        const progress = time / animationDuration;
        if (progress < 0.1) {
            // Резкий "взрыв" в первые 10%
            const explosionProgress = progress / 0.1;
            return 1 + Math.sin(explosionProgress * Math.PI) * 0.4;
        } else {
            // Плавное дыхание после взрыва
            const breathProgress = (progress - 0.1) / 0.9;
            const scaleWave = Math.sin(breathProgress * Math.PI * 3);
            return 1 + Math.abs(scaleWave) * 0.2;
        }
    }
    
    // Функция вращения всего колеса
    function wheelRotationEffect(time) {
        const progress = time / animationDuration;
        if (progress < 0.2) {
            // Быстрое покачивание в начале
            return Math.sin(progress * Math.PI * 20) * 3;
        } else {
            // Медленное покачивание
            const slowProgress = (progress - 0.2) / 0.8;
            return Math.sin(slowProgress * Math.PI * 2) * 2;
        }
    }
    
    // Функция рисования частиц
    function drawParticle(particle) {
        ctx.save();
        ctx.globalAlpha = particle.life;
        ctx.translate(particle.x, particle.y);
        ctx.rotate(particle.rotation);
        
        if (particle.type === 'star') {
            // Рисуем звездочку
            ctx.beginPath();
            for (let i = 0; i < 5; i++) {
                const angle = (i * Math.PI * 2) / 5;
                const outerRadius = particle.size;
                const innerRadius = particle.size * 0.5;
                
                const outerX = Math.cos(angle) * outerRadius;
                const outerY = Math.sin(angle) * outerRadius;
                const innerX = Math.cos(angle + Math.PI / 5) * innerRadius;
                const innerY = Math.sin(angle + Math.PI / 5) * innerRadius;
                
                if (i === 0) ctx.moveTo(outerX, outerY);
                else ctx.lineTo(outerX, outerY);
                ctx.lineTo(innerX, innerY);
            }
            ctx.closePath();
        } else {
            // Рисуем круг
            ctx.beginPath();
            ctx.arc(0, 0, particle.size, 0, Math.PI * 2);
        }
        
        ctx.fillStyle = particle.color;
        ctx.fill();
        ctx.strokeStyle = '#FFFFFF';
        ctx.lineWidth = 1;
        ctx.stroke();
        
        ctx.restore();
    }
    
    const animationInterval = setInterval(() => {
        animationTime += frameTime;
        
        // Проверка завершения анимации и очистка (первый блок)
        if (animationTime >= animationDuration) {
            clearInterval(animationInterval);
            
            // Восстанавливаем все оригинальные стили
            winningSegment.fillStyle = originalFillStyle;
            theWheel.strokeStyle = originalStrokeStyle; // Восстановлено
            theWheel.lineWidth = originalLineWidth;      // Восстановлено
            
            // Очищаем и перерисовываем
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            theWheel.draw(false);
            
            // Убираем CSS классы
            canvas.classList.remove('winner-glow');
            wheelWrapper.classList.remove('winner-glow');
            spinButton?.classList.remove('winner-celebration');
            document.querySelector('.stats')?.classList.remove('winner-celebration');
            mainContent?.classList.remove('winner-celebration');
            
            return;
        }
        
        // Вычисляем все эффекты
        const intensity = breathingEffect(animationTime);
        const scale = scaleEffect(animationTime);
        const wheelRotation = wheelRotationEffect(animationTime);
        
        // Очищаем canvas полностью
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // Сохраняем состояние для трансформации всего колеса
        ctx.save();
        
        // Применяем эффекты к всему колесу
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        
        ctx.translate(centerX, centerY);
        ctx.rotate((wheelRotation * Math.PI) / 180);
        ctx.translate(-centerX, -centerY);
        
        // Временно убираем обводку для чистой анимации (Пункт 1)
        theWheel.strokeStyle = 'transparent';
        theWheel.lineWidth = 0;
        
        // Перерисовываем основное колесо
        theWheel.draw(false);
        
        ctx.restore();
        
        // Обновляем и рисуем частицы
        ctx.save();
        particles.forEach(particle => {
            if (particle.life > 0) {
                particle.x += particle.vx;
                particle.y += particle.vy;
                particle.vy += 0.15; // Гравитация
                particle.vx *= 0.99; // Сопротивление воздуха
                particle.life -= particle.decay;
                particle.rotation += particle.rotationSpeed;
                
                drawParticle(particle);
            }
        });
        ctx.restore();
        
        // Анимация выигрышного сегмента
        ctx.save();
        
        // Получаем правильные углы
        const segmentNumber = theWheel.getIndicatedSegmentNumber();
        const segment = theWheel.segments[segmentNumber];
        
        const pointerOffset = -Math.PI / 2;
        const currentRotation = (theWheel.rotationAngle + wheelRotation) * Math.PI / 180;
        const startAngle = (segment.startAngle * Math.PI / 180) + currentRotation + pointerOffset;
        const endAngle = (segment.endAngle * Math.PI / 180) + currentRotation + pointerOffset;
        
        // Применяем масштабирование к сегменту
        ctx.translate(centerX, centerY);
        ctx.scale(scale, scale);
        ctx.translate(-centerX, -centerY);
        
        // Создаем путь для сегмента
        ctx.beginPath();
        ctx.moveTo(centerX, centerY);
        ctx.arc(centerX, centerY, theWheel.outerRadius, startAngle, endAngle, false);
        ctx.arc(centerX, centerY, theWheel.innerRadius, endAngle, startAngle, true);
        ctx.closePath();
        
        // Calculate gradient center for both S5 and S7
        const midAngle = (startAngle + endAngle) / 2;
        const gradientRadius = (theWheel.outerRadius + theWheel.innerRadius) / 2;
        const gradientX = centerX + Math.cos(midAngle) * gradientRadius;
        const gradientY = centerY + Math.sin(midAngle) * gradientRadius;

        // Многослойные эффекты свечения
        
        // Слой 1: Основное яркое свечение
        ctx.globalAlpha = intensity * 0.8;
        ctx.fillStyle = '#FFFFFF';
        ctx.fill();
        
        // Слой 2: Золотая обводка
        ctx.globalAlpha = intensity;
        ctx.strokeStyle = '#FFD700';
        ctx.lineWidth = 6 + Math.sin(animationTime * 0.02) * 3;
        ctx.stroke();
        
        // Слой 3: Светло-золотая обводка
        ctx.globalAlpha = intensity * 0.8;
        ctx.strokeStyle = '#FFF8DC';
        ctx.lineWidth = 4;
        ctx.stroke();
        
        // Слой 4: Темно-золотая обводка
        ctx.globalAlpha = intensity * 0.6;
        ctx.strokeStyle = '#DAA520';
        ctx.lineWidth = 2;
        ctx.stroke();
        
        // Слой 5: Премиум золотой градиент
        const gradient = ctx.createRadialGradient(
            gradientX, gradientY, 0,
            gradientX, gradientY, theWheel.outerRadius - theWheel.innerRadius
        );
        
        gradient.addColorStop(0, `rgba(255, 255, 255, ${intensity})`);
        gradient.addColorStop(0.2, `rgba(255, 215, 0, ${intensity * 0.9})`);
        gradient.addColorStop(0.4, `rgba(255, 223, 0, ${intensity * 0.8})`);
        gradient.addColorStop(0.6, `rgba(218, 165, 32, ${intensity * 0.6})`);
        gradient.addColorStop(0.8, `rgba(184, 134, 11, ${intensity * 0.4})`);
        gradient.addColorStop(1, 'rgba(255, 215, 0, 0)');
        
        ctx.globalAlpha = intensity * 0.9;
        ctx.fillStyle = gradient;
        ctx.fill();
        
        // Слой 6: Динамические лучи света - УДАЛЕН (Пункт 2)
        
        // Слой 7: Пульсирующие кольца вокруг сегмента
        if (intensity > 0.6) {
            const ringCount = 3;
            for (let ring = 0; ring < ringCount; ring++) {
                const ringProgress = (animationTime * 0.005 + ring * 0.3) % 1;
                const ringRadius = theWheel.outerRadius + ringProgress * 50;
                const ringAlpha = (1 - ringProgress) * intensity * 0.5;
                
                ctx.globalAlpha = ringAlpha;
                ctx.beginPath();
                ctx.arc(gradientX, gradientY, ringRadius, 0, Math.PI * 2);
                ctx.strokeStyle = `rgba(255, 215, 0, ${ringAlpha})`; // Original color, not asked to change
                ctx.lineWidth = 3;
                ctx.stroke();
            }
        }
        
        // Слой 8: Искрящиеся точки по краю сегмента
        if (intensity > 0.4) {
            const sparkCount = 16;
            for (let i = 0; i < sparkCount; i++) {
                const sparkAngle = startAngle + (endAngle - startAngle) * (i / (sparkCount - 1));
                const sparkRadius = theWheel.outerRadius + Math.sin(animationTime * 0.03 + i) * 8;
                const sparkX = centerX + Math.cos(sparkAngle) * sparkRadius;
                const sparkY = centerY + Math.sin(sparkAngle) * sparkRadius;
                const sparkSize = 2 + Math.sin(animationTime * 0.02 + i * 0.5) * 2;
                
                ctx.globalAlpha = intensity * (0.5 + Math.sin(animationTime * 0.02 + i) * 0.5);
                ctx.beginPath();
                ctx.arc(sparkX, sparkY, sparkSize, 0, Math.PI * 2);
                // Искры тоже золотые:
                ctx.fillStyle = i % 2 === 0 ? '#FFFFFF' : '#FFD700';
                ctx.fill();
                
                // Добавляем свечение к искрам
                ctx.shadowColor = ctx.fillStyle;
                ctx.shadowBlur = 10;
                ctx.fill();
                ctx.shadowBlur = 0;
            }
        }
        
        ctx.restore();
        
        // Дополнительный эффект: волны энергии от центра
        if (animationTime < 1000) { // Первая секунда
            const waveProgress = animationTime / 1000;
            const waveCount = 5;
            
            ctx.save();
            ctx.globalAlpha = (1 - waveProgress) * 0.6;
            
            for (let wave = 0; wave < waveCount; wave++) {
                const waveRadius = waveProgress * 300 + wave * 20;
                const waveAlpha = (1 - waveProgress) * (1 - wave / waveCount);
                
                ctx.globalAlpha = waveAlpha;
                ctx.beginPath();
                ctx.arc(centerX, centerY, waveRadius, 0, Math.PI * 2);
                ctx.strokeStyle = `rgba(255, 215, 0, ${waveAlpha})`; // Original color, not asked to change
                ctx.lineWidth = 2;
                ctx.stroke();
            }
            ctx.restore();
        }

        // Проверка завершения анимации и очистка (второй блок, был в оригинале)
        if (animationTime >= animationDuration) {
            clearInterval(animationInterval);
            
            // Восстанавливаем все оригинальные стили
            winningSegment.fillStyle = originalFillStyle;
            theWheel.strokeStyle = originalStrokeStyle; // Уже было в оригинале
            theWheel.lineWidth = originalLineWidth;      // Уже было в оригинале
            
            // Очищаем и перерисовываем
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            theWheel.draw(false);
            
            // Убираем все CSS классы
            canvas.classList.remove('winner-glow');
            wheelWrapper.classList.remove('winner-glow');
            spinButton.classList.remove('winner-celebration');
            document.querySelector('.stats').classList.remove('winner-celebration');
            mainContent.classList.remove('winner-celebration');
            
            return;
        }
        
    }, frameTime);
}

spinButton.addEventListener('click', async () => {
    if (wheelSpinning || !theWheel || currentUserInfo.available_spins <= 0) return;
    
    spinButton.disabled = true;
    wheelSpinning = true;
    spinButton.classList.remove('button-pulse-animation');
    updateSpinButtonText(); 

    try {
        const result = await apiFetch('/api/v1/spin', { 
            method: 'POST',
            body: JSON.stringify({ prizes: wheelConfig.prizes })
        });
        
        console.log("Backend response on spin:", result);

        if (!result.success || !result.prize) {
            throw new Error(result.error || i18n.alert_sync_error || 'Invalid server response.');
        }
        
        currentUserInfo.available_spins -= 1;
        updateUI();

        const winningPrize = result.prize;
        let winningSegmentNumber = 0;
        for (let i = 1; i <= theWheel.numSegments; i++) {
            if (theWheel.segments[i] && theWheel.segments[i].id === winningPrize.id) {
                winningSegmentNumber = i;
                break;
            }
        }

        if (winningSegmentNumber > 0) {
            // Сбрасываем угол поворота колеса перед каждым спином
            theWheel.rotationAngle = 0;
            
            let stopAtAngle = theWheel.getRandomForSegment(winningSegmentNumber);
            
            // Логика "Почти победы"
            const mythicSegment = theWheel.segments.find(s => s && s.id.startsWith('mythic'));
            if (mythicSegment) {
                const mythicSegmentNumber = theWheel.segments.findIndex(s => s && s.id === mythicSegment.id);
                const isNeighbor = Math.abs(winningSegmentNumber - mythicSegmentNumber) === 1;
        
                if (isNeighbor && Math.random() < 0.00) {
                    console.log("NEAR MISS TRIGGERED!");
                    // Останавливаем почти на mythic сегменте, но чуть-чуть не доходим
                    const mythicAngle = theWheel.getRandomForSegment(mythicSegmentNumber);
                    const offset = 5; // 5 градусов не доходим до mythic
                    stopAtAngle = mythicAngle + offset;
                }
            }
        
            theWheel.animation.spins = 12;
            theWheel.animation.stopAngle = stopAtAngle;
            theWheel.startAnimation();
            
            // Таймер для анимации победителя
            setTimeout(animateWinnerSegment, ANIMATION_DURATION_S * 1000);
            
            // Таймер для основной логики
            setTimeout(() => handleSpinResult(result), (ANIMATION_DURATION_S + 1.5) * 1000);

        } else {
            console.error("Winning prize ID from backend not found on the current wheel:", winningPrize.id);
            throw new Error(i18n.alert_sync_error || 'Sync error.');
        }

    } catch (error) {
        console.error("Spin Error:", error);
        tg.showAlert(error.message);
        wheelSpinning = false;
        await loadUserInfo();
    }
});

// <<< ИЗМЕНЕНИЕ: Эта функция теперь вызывается только из setTimeout >>>
async function handleSpinResult(resultData) {
    console.log("Handling result after all animations:", resultData);

    const prizeId = resultData.prize.id;
    const localizedPrizeName = wheelConfig.prizes.find(p => p.id === prizeId)?.localized_name || resultData.prize.name;

    const winMessage = i18n.alert_win_message 
        ? i18n.alert_win_message.replace('{prize_name}', localizedPrizeName) 
        : `Congratulations! You won: ${localizedPrizeName}`;
    
    await tg.showAlert(winMessage);
    
    await apiFetch('/api/v1/notify-win', {
        method: 'POST',
        body: JSON.stringify({ prize_data: resultData })
    });

    wheelSpinning = false;
    await loadUserInfo();
}

function updateUI() {
    animateValue(spinsCountEl, parseInt(spinsCountEl.textContent) || 0, currentUserInfo.available_spins, 500);
    animateValue(pointsCountEl, parseInt(pointsCountEl.textContent) || 0, currentUserInfo.loyalty_points, 500);
    
    spinButton.disabled = wheelSpinning || currentUserInfo.available_spins <= 0;
    updateSpinButtonText();
    
    if (!wheelSpinning && currentUserInfo.available_spins > 0) {
        spinButton.classList.add('button-pulse-animation');
    } else {
        spinButton.classList.remove('button-pulse-animation');
    }
}

// <<< ИЗМЕНЕНИЕ: Главный обработчик, который вызывается ПОСЛЕ остановки колеса >>>
function handleSpinAnimationFinished(resultData) {
    console.log("Spin animation finished. Result data:", resultData);
    // Запускаем анимацию пульсации, и ПОСЛЕ нее выполняем всю остальную логику
    animateWinnerSegment(async () => {
        const prizeId = resultData.prize.id;
        const localizedPrizeName = wheelConfig.prizes.find(p => p.id === prizeId)?.localized_name || resultData.prize.name;

        const winMessage = i18n.alert_win_message 
            ? i18n.alert_win_message.replace('{prize_name}', localizedPrizeName) 
            : `Congratulations! You won: ${localizedPrizeName}`;
        
        await tg.showAlert(winMessage);
        
        console.log("Sending notification to backend...");
        await apiFetch('/api/v1/notify-win', {
            method: 'POST',
            body: JSON.stringify({ prize_data: resultData })
        });
        console.log("Notification sent. Reloading user info...");

        wheelSpinning = false;
        await loadUserInfo();
    });
}



async function loadUserInfo() {
    try {
        const userInfo = await apiFetch('/api/v1/user-info');
        currentUserInfo.available_spins = userInfo.available_spins;
        currentUserInfo.loyalty_points = userInfo.loyalty_points;
        updateUI();
    } catch (error) {
        console.error("Failed to load user info:", error);
        spinButton.disabled = true;
        spinButtonText.textContent = i18n.spin_button_error || "Error";
    }
}

async function fetchWheelConfig() {
    return apiFetch('/api/v1/wheel-config');
}

async function apiFetch(endpoint, options = {}) {
    if (!tg.initData) throw new Error('Telegram initData is not available.');

    const defaultHeaders = { 'Authorization': `tma ${tg.initData}` };
    if (options.method === 'POST') {
        defaultHeaders['Content-Type'] = 'application/json';
        options.body = options.body || JSON.stringify({});
    }
    options.headers = { ...defaultHeaders, ...options.headers };

    try {
        const response = await fetch(`${BACKEND_URL}${endpoint}`, options);
        const responseText = await response.text();
        if (!response.ok) {
            let errorMsg = `Server Error: ${response.status}`;
            try { errorMsg = JSON.parse(responseText).error || errorMsg; } catch (e) {}
            throw new Error(errorMsg);
        }
        return responseText ? JSON.parse(responseText) : {};
    } catch (error) {
        console.error(`API Fetch Error for ${endpoint}:`, error);
        throw error;
    }
}

function animateValue(element, start, end, duration) {
    if (start === end) return;
    const range = end - start;
    const increment = range / (duration / 16);
    let current = start;
    const timer = setInterval(() => {
        current += increment;
        if ((increment > 0 && current >= end) || (increment < 0 && current <= end)) {
            current = end;
            clearInterval(timer);
        }
        element.textContent = Math.round(current);
    }, 16);
}