<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes, viewport-fit=cover">
    <title>{{ case_display_name }} - CS2 Simulator</title>
    <link rel="stylesheet" href="/static/css/style.css">
    <style>
        /* Стили для карточек (только для фарм-кейсов) */
        .cards-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
            gap: 12px;
            padding: 16px;
            perspective: 1000px;
        }
        
        .card-flip {
            aspect-ratio: 3/4;
            cursor: pointer;
            position: relative;
            transform-style: preserve-3d;
            transition: transform 0.6s cubic-bezier(0.4, 0.0, 0.2, 1);
        }
        
        .card-flip.flipped {
            transform: rotateY(180deg);
        }
        
        .card-front, .card-back {
            position: absolute;
            width: 100%;
            height: 100%;
            backface-visibility: hidden;
            border-radius: 8px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 8px;
            box-sizing: border-box;
        }
        
        .card-front {
            background: var(--bg-card);
            border: 2px solid var(--border-color);
            transform: rotateY(180deg);
        }
        
        .card-back {
            background: linear-gradient(135deg, #2a1a4e 0%, #1a0a2e 100%);
            border: 2px solid #8b7355;
            transform: rotateY(0deg);
            background-image: 
                repeating-linear-gradient(45deg, rgba(255,215,0,0.1) 0px, rgba(255,215,0,0.1) 2px, 
                                          transparent 2px, transparent 8px);
        }
        
        .card-back::before {
            content: "?";
            font-size: 48px;
            font-weight: bold;
            color: #ffd700;
            text-shadow: 0 0 20px #ffd700;
            opacity: 0.5;
        }
        
        .card-front img {
            width: 100%;
            height: 100px;
            object-fit: contain;
            margin-bottom: 4px;
        }
        
        .card-front .card-name {
            font-size: 9px;
            text-align: center;
            word-break: break-word;
            display: -webkit-box;
            -webkit-line-clamp: 3;
            -webkit-box-orient: vertical;
            overflow: hidden;
            width: 100%;
            margin-top: 4px;
        }
        
        .card-front .card-rarity {
            font-size: 8px;
            margin-top: 2px;
            font-weight: bold;
        }
        
        .card-front .card-float {
            font-size: 8px;
            color: var(--text-secondary);
            margin-top: 2px;
        }
        
        .card-front .card-price {
            font-size: 9px;
            color: var(--success-color);
            font-weight: bold;
            margin-top: 4px;
        }
        
        .card-flip.top-drop .card-front {
            border-color: #ffd700;
            box-shadow: 0 0 30px rgba(255, 215, 0, 0.5);
        }
        
        .cards-summary {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 16px;
            background: var(--bg-card);
            border-radius: 8px;
            margin: 12px 0;
        }
        
        .cards-actions {
            display: flex;
            gap: 8px;
        }
        
        .flip-progress {
            color: var(--text-secondary);
            font-size: 14px;
        }
        
        .no-topdrop-message {
            text-align: center;
            padding: 40px;
            background: var(--bg-card);
            border-radius: 12px;
            margin: 20px 0;
        }
        
        .no-topdrop-message h3 {
            color: #ef4444;
            margin-bottom: 12px;
        }
        
        .no-topdrop-message p {
            color: var(--text-secondary);
            margin-bottom: 20px;
        }
        
        /* Адаптация для мобильных */
        @media (max-width: 768px) {
            .cards-grid {
                grid-template-columns: repeat(3, 1fr);
                gap: 8px;
                padding: 8px;
            }
            
            .card-front img {
                height: 70px;
            }
            
            .card-back::before {
                font-size: 32px;
            }
        }
        
        @media (max-width: 480px) {
            .cards-grid {
                grid-template-columns: repeat(2, 1fr);
            }
        }
        
        @keyframes cardAppear {
            from {
                opacity: 0;
                transform: scale(0.8) rotateY(180deg);
            }
            to {
                opacity: 1;
                transform: scale(1) rotateY(180deg);
            }
        }
        
        .card-flip.appear {
            animation: cardAppear 0.4s ease-out;
        }
        
        .count-buttons {
            display: flex;
            gap: 4px;
            flex-wrap: wrap;
        }
        
        .count-btn {
            padding: 6px 12px;
            background: var(--bg-dark);
            border: 1px solid var(--border-color);
            color: var(--text-primary);
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.2s;
            min-width: 40px;
        }
        
        .count-btn.active {
            background: var(--primary-color);
            border-color: var(--primary-color);
        }
        
        .count-btn.farm-mode {
            background: linear-gradient(135deg, #2a1a4e, #1a0a2e);
            border-color: #ffd700;
        }
    </style>
</head>
<body>
    {% include "_nav.html" %}

    <main class="case-detail-container">
        <div class="container">
            <a href="/cases" class="back-link">← Назад к списку кейсов</a>
            
            <div class="case-header">
                <div class="case-title-row">
                    <div>
                        <h1>📦 {{ case_display_name }}</h1>
                        <p class="case-subtitle">{{ total_items }} предметов в кейсе</p>
                    </div>
                    <div class="case-info-badge">
                        <span class="case-price-tag">🔑 {{ case_price|money }} ₽ за шт.</span>
                    </div>
                </div>
                
                <div class="opening-controls">
                    {% if user %}
                    <div class="count-selector">
                        <label>Открыть:</label>
                        <div class="count-buttons" id="countButtons"></div>
                    </div>
                    <div class="total-price-display" id="totalPriceDisplay">
                        <span>Итого:</span> {{ case_price|money }} ₽
                    </div>
                    <button class="btn btn-primary btn-large" onclick="startOpening()" id="openButton">
                        🎲 Открыть
                    </button>
                    <button class="btn btn-fast" onclick="startOpening(true)" id="fastOpenButton" title="Быстрое открытие без анимации">⚡</button>
                    {% else %}
                    <div style="display:flex;align-items:center;gap:1rem;width:100%;justify-content:center;">
                        <span style="color:var(--text-secondary);">🔒 Войдите в аккаунт, чтобы открывать кейсы</span>
                        <a href="/login" class="btn btn-primary">Войти</a>
                        <a href="/register" class="btn btn-outline">Регистрация</a>
                    </div>
                    {% endif %}
                </div>
            </div>
            
            <div class="case-opening-section">
                <!-- Для слот-машины — всегда видна -->
                <div id="slotMachineContainer" style="display: none;">
                    <div class="slot-machine">
                        <div class="slot-reels">
                            <div class="slot-reel" id="slotReel0">
                                <div class="slot-track" id="slotTrack0"></div>
                            </div>
                            <div class="slot-reel" id="slotReel1">
                                <div class="slot-track" id="slotTrack1"></div>
                            </div>
                            <div class="slot-reel" id="slotReel2">
                                <div class="slot-track" id="slotTrack2"></div>
                            </div>
                            <div class="slot-win-line"></div>
                        </div>
                        <div class="slot-frame-glow" id="slotFrameGlow"></div>
                    </div>
                    <div class="slot-result-display" id="slotResultDisplay" style="display: none;"></div>
                    <div class="slot-legend" id="slotLegend">
                        <div class="slot-legend-header">
                            <span class="slot-legend-symbol">◆</span>
                            <span class="slot-legend-label">Активации</span>
                            <span class="slot-legend-symbol">◇</span>
                        </div>
                        <div class="slot-legend-grid">
                            <div class="slot-legend-card" data-act="extra_spin">
                                <span class="slc-icon" style="color:#8b5cf6;">🔄</span>
                                <span class="slc-name">Бонус-вращение</span>
                                <span class="slc-desc">Один барабан крутится заново</span>
                            </div>
                            <div class="slot-legend-card" data-act="double">
                                <span class="slc-icon" style="color:#f59e0b;">×2</span>
                                <span class="slc-name">Удвоение</span>
                                <span class="slc-desc">При совпадении приз ×2</span>
                            </div>
                            <div class="slot-legend-card" data-act="quintuple">
                                <span class="slc-icon" style="color:#ef4444;">×5</span>
                                <span class="slc-name">Квинтупль</span>
                                <span class="slc-desc">При совпадении приз ×5</span>
                            </div>
                            <div class="slot-legend-card" data-act="guaranteed">
                                <span class="slc-icon" style="color:#3b82f6;">🏷️</span>
                                <span class="slc-name">Гарант</span>
                                <span class="slc-desc">Предмет даже при провале</span>
                            </div>
                            <div class="slot-legend-card" data-act="free_spin">
                                <span class="slc-icon" style="color:#10b981;">🆓</span>
                                <span class="slc-name">Фриспин</span>
                                <span class="slc-desc">Следующая попытка бесплатно</span>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div id="openingAnimation" class="opening-animation-container" style="display: none;">
                    <!-- Для обычных кейсов - скроллы -->
                    <div id="singleScrollContainer" style="display: none;">
                        <div class="scroll-container-full" id="singleScrollContainerInner">
                            <div class="center-indicator-full"></div>
                            <div class="scroll-track-full" id="singleScrollTrack"></div>
                        </div>
                    </div>
                    <div id="multiScrollContainer" class="multi-scroll-grid" style="display: none;"></div>
                    
                    <!-- Для фарм-кейсов - карточки -->
                    <div id="farmCardsContainer" style="display: none;"></div>
                    
                </div>
                <div id="openingResults" style="display: none;"></div>
            </div>
            
            <div class="case-items-section">
                <h2>📋 Содержимое кейса ({{ total_items }} предметов)</h2>
                <div class="rarity-filters">
                    <button class="filter-btn active" onclick="filterItems('all')">Все</button>
                    {% for rarity in sorted_rarities %}
                    <button class="filter-btn" onclick="filterItems('{{ rarity }}')" 
                            style="color: var(--rarity-{{ rarity|lower|replace(' ', '-')|replace(' grade', '') }});">
                        {{ rarity }}
                    </button>
                    {% endfor %}
                </div>
                {% for rarity in sorted_rarities %}
                <div class="rarity-section" data-rarity="{{ rarity }}">
                    <h3 style="color: var(--rarity-{{ rarity|lower|replace(' ', '-')|replace(' grade', '') }}); border-bottom-color: var(--rarity-{{ rarity|lower|replace(' ', '-')|replace(' grade', '') }});">
                        {{ rarity }} 
                        <span class="rarity-count">({{ items_by_rarity[rarity]|length }})</span>
                    </h3>
                    
                    <div class="items-grid-compact">
                        {% for item in items_by_rarity[rarity] %}
                        <div class="item-card-compact" style="border-left-color: var(--rarity-{{ item.rarity|lower|replace(' ', '-')|replace(' grade', '') }});">
                            <img src="{{ item.image_url or '/static/placeholder.png' }}" 
                                 alt="{{ item.name }}"
                                 onerror="this.src='/static/placeholder.png'">
                            <div class="item-name-compact" title="{{ item.name }}">{{ item.name }}</div>
                            <div class="item-meta-compact">
                                <span>{{ item.type }}</span>
                                <span title="Шанс">{{ "%.2f"|format(item.probability) }}%</span>
                            </div>
                            <div class="item-meta-compact" style="margin-top: 3px;">
                                <span title="Float диапазон">Float: {{ "%.2f"|format(item.min_float) }} - {{ "%.2f"|format(item.max_float) }}</span>
                            </div>
                            {% if item.min_price and item.max_price %}
                            <div class="item-price-compact">
                                {% if item.min_price == item.max_price %}
                                    {{ item.min_price|money }} ₽
                                {% else %}
                                    {{ item.min_price|money }} - {{ item.max_price|money }} ₽
                                {% endif %}
                            </div>
                            {% endif %}
                        </div>
                        {% endfor %}
                    </div>
                </div>
                {% endfor %}
            </div>
        </div>
    </main>

    <script>
        // === Фразы для побед/поражений ===
        const PHRASE_PARTS = {
            win: {
                pre: ['🎉','🔥','⭐','🏆','💎','✨','🎯','👑','💫','🌟','🎰','💪','🥇','🎊','🏅'],
                verb: ['Победа','Джекпот','Успех','Красава','В дамках','Есть контакт','Повезло','Забрал','Выбил','Сорвал куш','Всё пучком','Лут','Топчик','Козырь','Фартануло'],
                noun: ['! 🔥','! 💎','! 🏆','! 👑','! ✨','! 💪','!','!','!'],
            },
            lose: {
                pre: ['😔','💔','😢','💀','😭','😤','😩','💸','😞','😓','🤡','💀','😅','🙃','🤷'],
                verb: ['Не повезло','Облом','Мимо','Пролёт','Не выпал','Не срослось','Пусто','Мимо кассы','В следующий раз','Не фортануло','Повезёт потом','Ноль','Минус','Увы','Печаль'],
                noun: [' 😔',' 💔','...',' 😢',' 😭',' 💸','...'],
            }
        };
        let usedPhraseKeys = new Set();
        function getRandomPhrase(type) {
            const parts = PHRASE_PARTS[type];
            for (let attempt = 0; attempt < 100; attempt++) {
                const pre = parts.pre[Math.floor(Math.random() * parts.pre.length)];
                const verb = parts.verb[Math.floor(Math.random() * parts.verb.length)];
                const noun = parts.noun[Math.floor(Math.random() * parts.noun.length)];
                const key = pre + '|' + verb + '|' + noun;
                if (!usedPhraseKeys.has(key)) {
                    usedPhraseKeys.add(key);
                    return pre + ' ' + verb + noun;
                }
            }
            usedPhraseKeys.clear();
            return getRandomPhrase(type);
        }

        let currentOpenCount = 1;
        let isOpening = false;
        let caseItems = {{ case_items|tojson }};
        let caseName = "{{ case_name }}";
        let casePrice = {{ case_price }};
        let userBalance = {{ user.balance }};
        window.lastOpenedItems = [];
        let freeSpinActive = false;
        
        // Флаг фарм-кейса / слот-машины
        const isFarmCase = caseName.toLowerCase().includes('фарм') || 
                          caseName.toLowerCase().includes('farm');
        const isSlotCase = caseName.toLowerCase().includes('slot') ||
                           caseName.toLowerCase().includes('слот');
        const maxCount = isSlotCase ? 1 : (isFarmCase ? 100 : 10);
        
        // Порог для топ-дропа (минимум 2× цена кейса)
        const TOP_DROP_THRESHOLD = Math.max(casePrice * 2, 5000);
        
        // Для фарм-кейсов
        let allFarmResults = [];
        let topDropItems = [];
        let trashItems = [];
        let revealedCards = 0;
        
        const RARITY_COLORS = {
            'consumer': '#b0b0b0',
            'industrial': '#5e98d9',
            'mil-spec': '#4b69ff',
            'restricted': '#8847ff',
            'classified': '#d32ce6',
            'covert': '#eb4b4b',
            'rare': '#ffd700',
            'extraordinary': '#ffd700',
            'contraband': '#ffaa00'
        };
        
        function getRarityColor(rarity) {
            if (!rarity) return '#b0b0b0';
            let key = rarity.toLowerCase()
                .replace(/ /g, '-')
                .replace(/'/g, '')
                .replace('grade', '')
                .replace(/-$/, '')
                .split('-')[0];
            return RARITY_COLORS[key] || '#b0b0b0';
        }
        
        function initCountButtons() {
            const container = document.getElementById('countButtons');
            let counts = [];
            
            if (isSlotCase) {
                counts = [1];
            } else if (isFarmCase) {
                counts = [1, 5, 10, 50, 100];
            } else {
                counts = Array.from({length: 10}, (_, i) => i + 1);
            }
            
            container.innerHTML = counts.map(count => 
                `<button onclick="setOpenCount(${count})" 
                         class="count-btn ${isFarmCase ? 'farm-mode' : ''} ${count === 1 ? 'active' : ''}" 
                         data-count="${count}">${count}</button>`
            ).join('');
        }
        
        function getItemDimensions(isMini) {
            const container = isMini ? 
                document.querySelector('.scroll-container-mini') : 
                document.querySelector('.scroll-container-full');
            
            if (!container) {
                const isMobile = window.innerWidth <= 480;
                if (isMini) {
                    return { itemWidth: isMobile ? 66 : 82, margin: isMobile ? 4 : 6 };
                } else {
                    return { itemWidth: isMobile ? 100 : 136, margin: isMobile ? 5 : 8 };
                }
            }
            
            const item = container.querySelector(isMini ? '.scroll-item-mini' : '.scroll-item-full');
            if (!item) return { itemWidth: isMini ? 82 : 136, margin: isMini ? 6 : 8 };
            
            const itemRect = item.getBoundingClientRect();
            const computedStyle = window.getComputedStyle(item);
            const marginLeft = parseFloat(computedStyle.marginLeft) || 0;
            const marginRight = parseFloat(computedStyle.marginRight) || 0;
            
            return {
                itemWidth: itemRect.width + marginLeft + marginRight,
                margin: marginLeft
            };
        }
        
        function updatePriceDisplay() {
            const totalPrice = casePrice * currentOpenCount;
            const priceElement = document.getElementById('totalPriceDisplay');
            const openButton = document.getElementById('openButton');
            if (priceElement) priceElement.innerHTML = `<span>Итого:</span> ${totalPrice.toLocaleString()} ₽`;
            if (openButton) {
                openButton.style.background = userBalance < totalPrice ? 'var(--danger-color)' : 'var(--primary-color)';
                openButton.title = userBalance < totalPrice ? 'Недостаточно средств' : '';
            }
        }
        
        async function refreshUserBalance() {
            try {
                const response = await fetch('/web/api/user/balance');
                const data = await response.json();
                if (data.success) {
                    userBalance = data.balance;
                    document.querySelectorAll('.user-balance').forEach(el => {
                        el.textContent = `${Math.floor(data.balance)} ₽`;
                    });
                    updatePriceDisplay();
                }
            } catch (e) {
                console.error('Ошибка обновления баланса:', e);
            }
        }

        async function refreshInventoryAjax() {
            try {
                const resp = await fetch('/web/api/inventory/items');
                const serverItems = await resp.json();
                window._inventoryItems = serverItems;
            } catch (e) {
                console.error('Failed to refresh inventory:', e);
            }
        }

        function resetCaseUI() {
            const openButton = document.getElementById('openButton');
            const animationDiv = document.getElementById('openingAnimation');
            const resultsDiv = document.getElementById('openingResults');
            const slotResultDisplay = document.getElementById('slotResultDisplay');

            openButton.disabled = false;
            openButton.textContent = isSlotCase ? '🎰 Открыть' : '🎲 Открыть';
            animationDiv.style.display = 'none';
            resultsDiv.style.display = 'none';
            resultsDiv.innerHTML = '';
            if (slotResultDisplay) {
                slotResultDisplay.style.display = 'none';
                slotResultDisplay.innerHTML = '';
            }
            isOpening = false;
            freeSpinActive = false;
            updatePriceDisplay();
        }
        
        function setOpenCount(count) {
            currentOpenCount = count;
            document.querySelectorAll('.count-btn').forEach(btn => {
                btn.classList.remove('active');
                if (parseInt(btn.dataset.count) === count) btn.classList.add('active');
            });
            updatePriceDisplay();
        }
        
        async function startOpening(fast) {
            if (isOpening) return;
            const totalPrice = casePrice * currentOpenCount;
            SoundManager.click();
            const hasFreeSpin = freeSpinActive;
            freeSpinActive = false;
            if (!hasFreeSpin && userBalance < totalPrice) {
                Notify.error(`Недостаточно средств! Нужно: ${totalPrice.toLocaleString()} ₽, у вас: ${Math.floor(userBalance).toLocaleString()} ₽`);
                isOpening = false;
                openButton.disabled = false;
                openButton.textContent = isSlotCase ? '🎰 Крутить' : '🎲 Открыть';
                return;
            }
            isOpening = true;
            
            const openButton = document.getElementById('openButton');
            const animationDiv = document.getElementById('openingAnimation');
            const resultsDiv = document.getElementById('openingResults');
            const singleContainer = document.getElementById('singleScrollContainer');
            const multiContainer = document.getElementById('multiScrollContainer');
            const farmCardsContainer = document.getElementById('farmCardsContainer');
            const slotContainer = document.getElementById('slotMachineContainer');
            
            openButton.disabled = true;
            openButton.textContent = isSlotCase ? '🎰 Крутим...' : '🎲 Открываем...';
            const fastBtn = document.getElementById('fastOpenButton');
            if (fastBtn) fastBtn.disabled = true;
            animationDiv.style.display = 'block';
            resultsDiv.style.display = 'none';
            resultsDiv.innerHTML = '';
            
            // Скрываем все контейнеры
            singleContainer.style.display = 'none';
            multiContainer.style.display = 'none';
            farmCardsContainer.style.display = 'none';
            slotContainer.style.display = 'none';
            
            try {
                if (isSlotCase) {
                    // ===== СЛОТ-МАШИНА: 3 БАРАБАНА =====
                    slotContainer.style.display = 'block';
                    window.caseItems = caseItems;
                    
                    const formData = new FormData();
                    formData.append('case_name', caseName);
                    if (hasFreeSpin) {
                        formData.append('free_spin', '1');
                    }

                    // Отправляем запрос на сервер (он вернёт 3 результата)
                    const response = await fetch('/web/api/cases/open/slot', {
                        method: 'POST',
                        body: formData
                    });
                    
                    const data = await response.json();
                    
                    if (data.success) {
                        handleAchievements(data);
                        SoundManager.slotSpin();
                        await animateSlots(data.reels, data.match, data.prize, data.bonus, data.spent, data.activations || [], data.multiplier || 0, data.multiplied_prize || null);
                        
                        if (data.new_balance !== undefined) userBalance = data.new_balance;
                        await refreshUserBalance();
                    } else {
                        Notify.error(data.error || 'Ошибка при открытии');
                    }
                } else if (isFarmCase) {
                    // ===== ФАРМ-КЕЙС: КАРТОЧКИ С АВТОПРОДАЖЕЙ ШЛАКА =====
                    farmCardsContainer.style.display = 'block';
                    
                    const formData = new FormData();
                    formData.append('case_name', caseName);
                    formData.append('count', currentOpenCount);
                    
                    const response = await fetch('/web/api/cases/open/multiple', {
                        method: 'POST',
                        body: formData
                    });
                    
                    const data = await response.json();
                    
                    if (data.success) {
                        handleAchievements(data);
                        SoundManager.caseOpen();
                        allFarmResults = data.results;
                        window.lastOpenedItems = data.results;
                        
                        // Разделяем на топ-дроп и шлак
                        separateItems();
                        
                        // Автоматически продаём шлак
                        if (trashItems.length > 0) {
                            await sellTrashItems();
                        }
                        
                        // Показываем результат
                        displayFarmResult();
                        
                        if (data.new_balance !== undefined) {
                            userBalance = data.new_balance;
                        }
                        await refreshUserBalance();
                    } else {
                        Notify.error(data.error || 'Ошибка при открытии');
                    }
                } else if (fast) {
                    // ===== БЫСТРОЕ ОТКРЫТИЕ БЕЗ АНИМАЦИИ =====
                    const formData = new FormData();
                    formData.append('case_name', caseName);
                    formData.append('count', String(currentOpenCount));

                    const response = await fetch('/web/api/cases/open/multiple', {
                        method: 'POST',
                        body: formData
                    });

                    const data = await response.json();

                    if (data.success) {
                        handleAchievements(data);
                        SoundManager.caseOpen();
                        window.lastOpenedItems = data.results;
                        showResults(data.results);
                        if (data.new_balance !== undefined) userBalance = data.new_balance;
                        await refreshUserBalance();
                    } else {
                        Notify.error(data.error || 'Ошибка при открытии');
                    }
                } else {
                    // ===== ОБЫЧНЫЙ КЕЙС: СКРОЛЛЫ (РУЛЕТКА) =====
                    if (currentOpenCount === 1) {
                        singleContainer.style.display = 'block';
                        // Add highlight ring
                        let ring = singleContainer.querySelector('.target-highlight-ring');
                        if (!ring) {
                            ring = document.createElement('div');
                            ring.className = 'target-highlight-ring';
                            singleContainer.appendChild(ring);
                        }
                        const track = document.getElementById('singleScrollTrack');
                        SoundManager.caseOpen();
                        const result = await animateSingleScroll(track);
                        if (result) {
                            window.lastOpenedItems = result.results;
                            showResults(result.results);
                            if (result.new_balance !== undefined) userBalance = result.new_balance;
                        }
                    } else {
                        multiContainer.style.display = 'grid';
                        
                        let cols;
                        const screenWidth = window.innerWidth;
                        if (screenWidth <= 480) cols = 2;
                        else if (screenWidth <= 768) cols = currentOpenCount <= 4 ? 2 : 3;
                        else cols = currentOpenCount <= 2 ? currentOpenCount : currentOpenCount <= 4 ? 2 : currentOpenCount <= 6 ? 3 : currentOpenCount <= 9 ? 3 : 5;
                        
                        multiContainer.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
                        multiContainer.innerHTML = '';
                        
                        // ⚡ ОПТИМИЗАЦИЯ: 1 запрос на N открытий
                        const batchData = await (async () => {
                            const fd = new FormData();
                            fd.append('case_name', caseName);
                            fd.append('count', String(currentOpenCount));
                            const r = await fetch('/web/api/cases/open/multiple', { method: 'POST', body: fd });
                            return await r.json();
                        })();
                        
                        if (!batchData.success) {
                            Notify.error(batchData.error || 'Ошибка при открытии');
                        } else {
                            handleAchievements(batchData);
                            SoundManager.caseOpen();
                            
                            const tracks = [];
                            for (let i = 0; i < currentOpenCount; i++) {
                                const wrapper = document.createElement('div');
                                wrapper.className = 'scroll-wrapper-full';
                                wrapper.innerHTML = `
                                    <div class="scroll-container-mini">
                                        <div class="center-indicator-mini"></div>
                                        <div class="scroll-track-mini" id="track${i}"></div>
                                    </div>
                                    <div class="scroll-label">Кейс #${i + 1}</div>
                                `;
                                multiContainer.appendChild(wrapper);
                                tracks.push(wrapper.querySelector('.scroll-track-mini'));
                            }
                            
                            const results = await Promise.all(tracks.map((track, i) => animateMiniScroll(track, i, batchData.results[i])));
                            const validResults = results.filter(r => r !== null);
                            if (validResults.length > 0) {
                                const allItems = validResults.flatMap(r => r.results);
                                window.lastOpenedItems = allItems;
                                showResults(allItems);
                            }
                            if (batchData.new_balance !== undefined) userBalance = batchData.new_balance;
                        }
                    }
                    await refreshUserBalance();
                }
            } catch (error) {
                console.error('Error opening cases:', error);
                Notify.error('Ошибка при открытии кейсов');
            } finally {
                isOpening = false;
                openButton.disabled = false;
                openButton.textContent = isSlotCase ? '🎰 Открыть' : '🎲 Открыть';
                const fastBtn = document.getElementById('fastOpenButton');
                if (fastBtn) fastBtn.disabled = false;
                if (!isFarmCase || (isFarmCase && topDropItems.length === 0)) {
                    // Не скрываем анимацию для фарм-кейса с сообщением "нет дропа"
                    animationDiv.style.display = 'none';
                }
                updatePriceDisplay();
            }
        }
        
        // ===== СЛОТ-МАШИНА =====
        function initSlotUI() {
            if (!isSlotCase) return;

            const slotContainer = document.getElementById('slotMachineContainer');
            slotContainer.style.display = 'block';

            // Hide count selector and fast button for slot
            const countSelector = document.querySelector('.count-selector');
            if (countSelector) countSelector.style.display = 'none';
            const fastBtn = document.getElementById('fastOpenButton');
            if (fastBtn) fastBtn.style.display = 'none';
            
            // Change button text
            const openButton = document.getElementById('openButton');
            if (openButton) openButton.textContent = '🎰 Открыть';
            
            // Fill reels with placeholder items
            const placeholderItems = caseItems.slice(0, 9);
            while (placeholderItems.length < 9) {
                placeholderItems.push(caseItems[Math.floor(Math.random() * caseItems.length)]);
            }
            for (let i = 0; i < 3; i++) {
                const track = document.getElementById(`slotTrack${i}`);
                const chunk = placeholderItems.slice(i * 3, i * 3 + 3);
                track.innerHTML = chunk.map((it, idx) => {
                    const rarityKey = (it.rarity || '').toLowerCase().replace(/ /g, '-').replace(/'/g, '').replace('grade', '').replace(/-$/, '');
                    const color = RARITY_COLORS[rarityKey] || '#b0b0b0';
                    return `<div class="slot-item" style="border-color: ${color}; opacity: 0.5;">
                        <img src="${it.image_url || '/static/placeholder.png'}" onerror="this.src='/static/placeholder.png'">
                        <span class="slot-item-name">${it.name || it.base_name || '???'}</span>
                    </div>`;
                }).join('');
            }
        }

        const ACTIVATION_DESC = {
            'extra_spin': '🔄 Дополнительное вращение — один барабан крутится снова',
            'double': '2x Удвоение приза — при совпадении приз ×2',
            'quintuple': '5x Увеличение приза — при совпадении приз ×5',
            'guaranteed': '🏷️ Гарантированный приз — получишь предмет даже при проигрыше',
            'free_spin': '🆓 Бесплатное открытие — следующая попытка бесплатно'
        };

        function buildSlotItems(caseItems, serverItem, length, activation) {
            const items = [];
            for (let i = 0; i < length; i++) {
                const ri = caseItems[Math.floor(Math.random() * caseItems.length)];
                // Cosmetic badges for visual variety
                let badge = '';
                if (i !== length - 8 && Math.random() < 0.04) {
                    const cosmetic = ['extra_spin', 'guaranteed', 'free_spin'][Math.floor(Math.random() * 3)];
                    badge = cosmetic;
                }
                items.push({...ri, _badge: badge});
            }
            // Place target item near the end (position length-8) with its server activation
            const targetPos = length - 8;
            items[targetPos] = {...serverItem, _isTarget: true, _isTargetIdx: targetPos, _badge: activation || ''};
            return items;
        }

        function renderSlotTrack(trackEl, items) {
            trackEl.innerHTML = items.map((it, idx) => {
                const rarityKey = (it.rarity || '').toLowerCase().replace(/ /g, '-').replace(/'/g, '').replace('grade', '').replace(/-$/, '');
                const color = RARITY_COLORS[rarityKey] || '#b0b0b0';
                const badge = it._badge;
                const badgeHtml = badge ? `<span class="slot-badge slot-badge-${badge}" title="${ACTIVATION_DESC[badge] || ''}">${
                    {'extra_spin': '🔄', 'double': '2x', 'guaranteed': '🏷️', 'free_spin': '🆓', 'quintuple': '5x'}[badge] || ''
                }</span>` : '';
                return `<div class="slot-item" data-index="${idx}" style="border-color: ${color};">
                    ${badgeHtml}
                    <img src="${it.image_url || '/static/placeholder.png'}" onerror="this.src='/static/placeholder.png'">
                    <span class="slot-item-name">${it.name || it.base_name || '???'}</span>
                </div>`;
            }).join('');
        }

        async function animateSlots(reelResults, match, prize, bonus, spent, activations, multiplier, multipliedPrize) {
            const slotContainer = document.getElementById('slotMachineContainer');
            const resultDisplay = document.getElementById('slotResultDisplay');
            resultDisplay.style.display = 'none';
            resultDisplay.innerHTML = '';

            // Reset frame glow
            const glow = document.getElementById('slotFrameGlow');
            glow.style.borderColor = 'transparent';
            glow.style.boxShadow = 'none';

            // Speed lines
            const speedLines = document.createElement('div');
            speedLines.className = 'scroll-speed-lines';
            slotContainer.querySelector('.slot-machine').appendChild(speedLines);

            // Build reels — 80 items each, target at index 72
            const caseItems = window.caseItems || [];
            const REEL_ITEMS = 80;
            const TARGET_POS = 72;
            const ITEM_H = 80;
            const WIN_Y = 80; // top of item when item center is at reel center (120 - 40)
            const reelItems = [];

            for (let i = 0; i < 3; i++) {
                reelItems.push(buildSlotItems(caseItems, reelResults[i], REEL_ITEMS, activations[i] || ''));
                const track = document.getElementById(`slotTrack${i}`);
                renderSlotTrack(track, reelItems[i]);
                // Reset position
                track.style.transition = 'none';
                track.style.transform = 'translateY(0px)';
                void track.offsetHeight;
            }

            // Final positions for each reel
            const finalY = reelItems.map(items => -(TARGET_POS * ITEM_H) + WIN_Y);

            // Stop timings: 3.5s, 5.25s, 7s
            const reelStopTimes = [3500, 5250, 7000];
            const reelDecelDurations = [800, 800, 800]; // snap duration

            let reelStopped = [false, false, false];
            let reelProgress = [0, 0, 0];

            const TOTAL_TIME = 7000;
            const startTime = performance.now();
            let animId = null;
            let resolveAnimation = null;
            const animPromise = new Promise(resolve => { resolveAnimation = resolve; });

            function slotEase(t) {
                // Wind-up phase: 0-12% time → 0-3% progress (slow cocking)
                if (t < 0.12) return (t / 0.12) * 0.03;
                // Release phase: 12-25% time → 3-20% progress (sudden acceleration)
                if (t < 0.25) {
                    const p = (t - 0.12) / 0.13;
                    return 0.03 + p * p * 0.17;
                }
                // Fast spin: 25-82% time → 20-90% progress
                if (t < 0.82) {
                    const p = (t - 0.25) / 0.57;
                    return 0.20 + p * 0.70;
                }
                // Deceleration: 82-100% time → 90-100% progress
                const p = (t - 0.82) / 0.18;
                // Sharp ease-out with slight overshoot at end
                const eased = 1 - Math.pow(1 - p, 4);
                const overshoot = 1 + 0.03 * Math.sin(p * Math.PI) * (1 - p);
                return 0.90 + 0.10 * eased * overshoot;
            }

            function tick() {
                const elapsed = performance.now() - startTime;
                const t = Math.min(elapsed / TOTAL_TIME, 1);
                const progress = slotEase(t); // 0 → ~1

                for (let i = 0; i < 3; i++) {
                    if (reelStopped[i]) continue;

                    if (elapsed >= reelStopTimes[i]) {
                        // Snap to final with CSS transition
                        reelStopped[i] = true;
                        const track = document.getElementById(`slotTrack${i}`);
                        track.style.transition = `transform ${reelDecelDurations[i]}ms cubic-bezier(0.05, 0.7, 0.2, 1.0)`;
                        track.style.transform = `translateY(${finalY[i]}px)`;
                        continue;
                    }

                    // During spin: progress drives position
                    const track = document.getElementById(`slotTrack${i}`);
                    const currentY = finalY[i] * progress;
                    track.style.transform = `translateY(${currentY}px)`;
                }

                if (t < 1) {
                    animId = requestAnimationFrame(tick);
                } else {
                    // Ensure all reels are at final position
                    for (let i = 0; i < 3; i++) {
                        if (!reelStopped[i]) {
                            const track = document.getElementById(`slotTrack${i}`);
                            track.style.transition = `transform ${reelDecelDurations[i]}ms cubic-bezier(0.05, 0.7, 0.2, 1.0)`;
                            track.style.transform = `translateY(${finalY[i]}px)`;
                            reelStopped[i] = true;
                        }
                    }
                    onSpinComplete();
                }
            }

            function onSpinComplete() {
                // Remove speed lines
                if (speedLines.parentNode) speedLines.parentNode.removeChild(speedLines);

                // Clear transitions after snap
                setTimeout(() => {
                    for (let i = 0; i < 3; i++) {
                        const track = document.getElementById(`slotTrack${i}`);
                        track.style.transition = 'none';
                        // Highlight target
                        const els = track.querySelectorAll('.slot-item');
                        if (els[TARGET_POS]) els[TARGET_POS].classList.add('slot-item-hit');
                    }
                }, reelDecelDurations[2] + 50);

                // Flash + particles
                const rarityColors = ['gold', 'blue', 'purple', 'pink', 'red'];
                const flashColor = rarityColors[Math.floor(Math.random() * rarityColors.length)];
                flashBurst(slotContainer.querySelector('.slot-machine'), flashColor);
                particleBurst(slotContainer.querySelector('.slot-machine'), flashColor, 30);

                // Glow frame
                const glow = document.getElementById('slotFrameGlow');
                if (match) {
                    glow.style.borderColor = '#ffd700';
                    glow.style.boxShadow = '0 0 60px rgba(255,215,0,0.5), inset 0 0 60px rgba(255,215,0,0.15)';
                } else {
                    glow.style.borderColor = '#ef4444';
                    glow.style.boxShadow = '0 0 40px rgba(239,68,68,0.3), inset 0 0 40px rgba(239,68,68,0.1)';
                }

                // Show result
                setTimeout(() => {
                    if (match && prize) {
                        let items = [prize];
                        let winNote = 'Совпадение на всех барабанах!';
                        if (multiplier > 1 && multipliedPrize) {
                            items = [multipliedPrize];
                            winNote = `💥 Множитель x${multiplier}! Приз увеличен!`;
                            particleBurst(slotContainer.querySelector('.slot-machine'), 'gold', 60);
                        } else if (bonus) {
                            items.push(bonus);
                        }
                        window.lastOpenedItems = items;
                        showResults(items);

                        resultDisplay.style.display = 'block';
                        resultDisplay.innerHTML = `
                            <div class="slot-win-banner">
                                <div class="slot-win-title">${getRandomPhrase('win')}</div>
                                <div class="slot-win-subtitle">${winNote}</div>
                            </div>
                        `;
                        particleBurst(slotContainer.querySelector('.slot-machine'), 'gold', 40);
                    } else if (prize && !match) {
                        // Guaranteed consolation
                        window.lastOpenedItems = [prize];
                        showResults([prize]);
                        resultDisplay.style.display = 'block';
                        resultDisplay.innerHTML = `
                            <div class="slot-win-banner" style="border-color: rgba(59,130,246,0.4);">
                                <div class="slot-win-title" style="color: #3b82f6;">🏷️ Гарантированный приз!</div>
                                <div class="slot-win-subtitle">Активация сработала — ты получил предмет!</div>
                            </div>
                        `;
                        particleBurst(slotContainer.querySelector('.slot-machine'), '#3b82f6', 30);
                    } else {
                        resultDisplay.style.display = 'block';
                        resultDisplay.innerHTML = `
                            <div class="slot-lose-banner">
                                <div class="slot-lose-title">${getRandomPhrase('lose')}</div>
                                <div class="slot-lose-subtitle">Повезёт в следующий раз!</div>
                            </div>
                        `;
                    }

                    // Check for free spin activation
                    if (!match && activations.includes('free_spin')) {
                        freeSpinActive = true;
                        const openButton = document.getElementById('openButton');
                        openButton.disabled = false;
                        openButton.textContent = '🆓 Бесплатно!';
                    }

                    slotContainer.querySelector('.slot-machine').appendChild(resultDisplay);
                    refreshUserBalance();
                    if (resolveAnimation) resolveAnimation();
                }, 600);
            }

            animId = requestAnimationFrame(tick);
            return animPromise;
        }

        // ===== ФУНКЦИИ ДЛЯ ФАРМ-КЕЙСОВ =====
        function separateItems() {
            topDropItems = [];
            trashItems = [];
            
            for (const item of allFarmResults) {
                if (item.price > TOP_DROP_THRESHOLD) {
                    topDropItems.push(item);
                } else {
                    trashItems.push(item);
                }
            }
        }
        
        async function sellTrashItems() {
            try {
                const response = await fetch('/web/api/inventory/items');
                const items = await response.json();
                
                const inventoryIds = [];
                for (const trashItem of trashItems) {
                    const invItem = items.find(i => i.item_id === trashItem.id && 
                                                   Math.abs(i.float - trashItem.float) < 0.001);
                    if (invItem) {
                        inventoryIds.push(invItem.id);
                    }
                }
                
                if (inventoryIds.length > 0) {
                    const formData = new FormData();
                    formData.append('inventory_ids', JSON.stringify(inventoryIds));
                    
                    await fetch('/web/api/inventory/sell/bulk', {
                        method: 'POST',
                        body: formData
                    });
                }
            } catch (e) {
                console.error('Ошибка продажи шлака:', e);
            }
        }
        
        function displayFarmResult() {
            const farmContainer = document.getElementById('farmCardsContainer');
            
            if (topDropItems.length === 0) {
                farmContainer.innerHTML = `
                    <div class="no-topdrop-message">
                        <h3>😕 Увы, топ-дропа не оказалось</h3>
                        <p>Открыто ${currentOpenCount} кейсов, но ничего ценного не выпало.</p>
                        <p style="color: var(--success-color);">💰 Шлак (${trashItems.length} предметов) автоматически продан.</p>
                        <button class="btn btn-primary" onclick="tryAgain()">🎲 Попробовать ещё</button>
                        <button class="btn btn-outline" onclick="resetCaseUI()">↻ Вернуться</button>
                    </div>
                `;
            } else {
                revealedCards = 0;
                
                let html = `
                    <div class="cards-summary">
                        <span class="flip-progress" id="flipProgress">0/${topDropItems.length} топ-дропов</span>
                        <div class="cards-actions">
                            <button class="btn btn-success btn-sm" onclick="revealAllCards()">✨ Открыть все</button>
                            <button class="btn btn-outline btn-sm" onclick="resetCardsView()">↻ Сбросить</button>
                        </div>
                    </div>
                    <div class="cards-grid" id="cardsGrid"></div>
                    <div style="margin-top: 16px; text-align: center; color: var(--text-secondary);">
                        💰 Шлак (${trashItems.length} предметов) автоматически продан
                    </div>
                `;
                
                farmContainer.innerHTML = html;
                
                const grid = document.getElementById('cardsGrid');
                topDropItems.forEach((item, index) => {
                    const color = getRarityColor(item.rarity);
                    const card = document.createElement('div');
                    card.className = 'card-flip top-drop appear';
                    card.dataset.index = index;
                    card.dataset.revealed = 'false';
                    
                    card.innerHTML = `
                        <div class="card-front" style="border-color: ${color}; box-shadow: 0 0 20px ${color}40;">
                            <img src="${item.image_url || '/static/placeholder.png'}" onerror="this.src='/static/placeholder.png'">
                            <div class="card-name" title="${item.name}">${item.name}</div>
                            <div class="card-rarity" style="color: ${color};">${item.rarity}</div>
                            <div class="card-float">Float: ${item.float.toFixed(6)}</div>
                            <div class="card-price">💰 ${Math.floor(item.price).toLocaleString()} ₽</div>
                        </div>
                        <div class="card-back"></div>
                    `;
                    
                    card.onclick = () => flipCard(card, index);
                    grid.appendChild(card);
                });
            }
        }
        
        function flipCard(card, index) {
            if (card.classList.contains('flipped')) return;
            if (card.dataset.revealed === 'true') return;
            
            card.classList.add('flipped');
            card.dataset.revealed = 'true';
            revealedCards++;
            
            // Particle burst on flip
            const rarity = card.querySelector('.card-rarity')?.textContent || '';
            const burst = document.createElement('div');
            burst.className = 'particle-burst';
            burst.style.inset = '-20px';
            card.appendChild(burst);
            const colors = ['#ffd700', '#f59e0b', '#fff'];
            for (let i = 0; i < 8; i++) {
                const pt = document.createElement('div');
                pt.className = 'pt';
                pt.style.setProperty('--px', (Math.random() - 0.5) * 100 + 'px');
                pt.style.setProperty('--py', -(Math.random() * 80 + 10) + 'px');
                pt.style.background = colors[Math.floor(Math.random() * colors.length)];
                pt.style.left = '40%';
                pt.style.top = '50%';
                pt.style.animationDelay = Math.random() * 0.1 + 's';
                pt.style.width = (2 + Math.random() * 3) + 'px';
                pt.style.height = pt.style.width;
                burst.appendChild(pt);
            }
            setTimeout(() => burst.remove(), 1000);
            
            updateFlipProgress();
            
            if (revealedCards === topDropItems.length) {
                setTimeout(() => {
                    if (topDropItems.length > 0) {
                        showFarmResults(topDropItems);
                    }
                }, 500);
            }
        }
        
        function revealAllCards() {
            const cards = document.querySelectorAll('.card-flip');
            
            cards.forEach((card, index) => {
                if (card.dataset.revealed === 'false') {
                    setTimeout(() => {
                        card.classList.add('flipped');
                        card.dataset.revealed = 'true';
                    }, index * 100);
                }
            });
            
            revealedCards = topDropItems.length;
            updateFlipProgress();
            
            setTimeout(() => {
                if (topDropItems.length > 0) {
                    showFarmResults(topDropItems);
                }
            }, topDropItems.length * 100 + 500);
        }
        
        function resetCardsView() {
            const cards = document.querySelectorAll('.card-flip');
            cards.forEach(card => {
                card.classList.remove('flipped');
                card.dataset.revealed = 'false';
            });
            revealedCards = 0;
            updateFlipProgress();
        }
        
        function updateFlipProgress() {
            const progressEl = document.getElementById('flipProgress');
            if (progressEl) {
                progressEl.textContent = `${revealedCards}/${topDropItems.length} топ-дропов`;
            }
        }
        
        function tryAgain() {
            const animationDiv = document.getElementById('openingAnimation');
            animationDiv.style.display = 'none';
            startOpening();
        }
        
        function showFarmResults(results) {
            const resultsDiv = document.getElementById('openingResults');
            const animationDiv = document.getElementById('openingAnimation');
            
            animationDiv.style.display = 'none';
            
            const grouped = {};
            results.forEach((item) => {
                const key = item.name;
                if (!grouped[key]) {
                    grouped[key] = { ...item, count: 1 };
                } else {
                    grouped[key].count++;
                }
            });
            
            let totalValue = results.reduce((sum, item) => sum + (item.price || 100), 0);
            
            let html = `
                <div class="case-results-header">
                    <div class="case-results-title">🎉 Топ-дропы (${results.length})</div>
                    <div class="case-results-actions">
                        <button class="btn btn-success btn-sm" onclick="sellAllTopDrops()">
                            💰 Продать всё (${totalValue.toLocaleString()} ₽)
                        </button>
                        <button class="btn btn-outline btn-sm" onclick="resetCaseUI()">↻ Ещё</button>
                    </div>
                </div>
                <div class="results-grid-enhanced">
            `;
            
            Object.values(grouped).forEach((item, idx) => {
                const color = getRarityColor(item.rarity);
                html += `
                    <div class="result-card-enhanced" style="animation-delay: ${idx * 0.06}s; --glow: ${color};">
                        <div class="result-card-glow" style="background: radial-gradient(ellipse at center, ${color}20, transparent 70%);"></div>
                        <img src="${item.image_url || '/static/placeholder.png'}" onerror="this.src='/static/placeholder.png'">
                        <div class="result-card-body">
                            <div class="result-name-enhanced" title="${item.name}">${item.name}</div>
                            <div class="result-meta-enhanced">
                                <span style="color: ${color};">${item.rarity}</span>
                            </div>
                            <div class="result-footer-enhanced">
                                <span class="result-price-enhanced">${(item.price || 100).toLocaleString()} ₽</span>
                            </div>
                        </div>
                        ${item.count > 1 ? `<span class="result-count-badge">x${item.count}</span>` : ''}
                    </div>
                `;
            });
            
            html += `</div>`;
            
            resultsDiv.innerHTML = html;
            resultsDiv.style.display = 'block';
        }
        
        async function sellAllTopDrops() {
            if (topDropItems.length === 0) {
                Notify.error('Нет предметов для продажи');
                return;
            }
            
            const total = topDropItems.reduce((sum, i) => sum + (i.price || 100), 0);
            Notify.confirm('Продать все топ-дропы за ' + total.toLocaleString() + ' ₽?', 'Продажа', async function(confirmed) {
                if (!confirmed) return;
                try {
                    const response = await fetch('/web/api/inventory/items');
                    const items = await response.json();
                    
                    const inventoryIds = [];
                    for (const item of topDropItems) {
                        const invItem = items.find(i => i.item_id === item.id && 
                                                       Math.abs(i.float - item.float) < 0.001);
                        if (invItem) {
                            inventoryIds.push(invItem.id);
                        }
                    }
                    
                    if (inventoryIds.length > 0) {
                        const formData = new FormData();
                        formData.append('inventory_ids', JSON.stringify(inventoryIds));
                        
                        await fetch('/web/api/inventory/sell/bulk', {
                            method: 'POST',
                            body: formData
                        });
                    }
                    
                    await refreshUserBalance();
                    await refreshInventoryAjax();
                    topDropItems = [];
                    resetCaseUI();
                } catch (error) {
                    Notify.error('Ошибка соединения');
                }
            });
        }
        
        // ===== ЭФФЕКТЫ =====
        function addSpeedLines(container) {
            const el = document.createElement('div');
            el.className = 'scroll-speed-lines';
            el.id = 'speedLines_' + Math.random().toString(36).slice(2);
            container.appendChild(el);
            return el;
        }

        function removeSpeedLines(el) {
            if (el && el.parentNode) el.parentNode.removeChild(el);
        }

        function flashBurst(container, rarity) {
            const flash = document.createElement('div');
            flash.className = 'scroll-flash burst';

            const r = (rarity || '').toLowerCase();
            if (r.includes('covert') || r.includes('red')) flash.classList.add('red');
            else if (r.includes('classified') || r.includes('pink')) flash.classList.add('pink');
            else if (r.includes('restricted') || r.includes('purple')) flash.classList.add('purple');
            else if (r.includes('mil-spec') || r.includes('blue')) flash.classList.add('blue');
            else flash.classList.add('gold');

            container.appendChild(flash);
            requestAnimationFrame(() => {
                flash.style.opacity = '1';
                setTimeout(() => {
                    flash.style.transition = 'opacity 0.4s';
                    flash.style.opacity = '0';
                    setTimeout(() => flash.remove(), 500);
                }, 200);
            });
        }

        function particleBurst(container, rarity, count) {
            const burst = document.createElement('div');
            burst.className = 'particle-burst';
            container.appendChild(burst);

            const r = (rarity || '').toLowerCase();
            let colors = ['#ffd700', '#f59e0b'];
            if (r.includes('covert') || r.includes('red')) colors = ['#eb4b4b', '#ff6b6b', '#ffd700'];
            else if (r.includes('classified') || r.includes('pink')) colors = ['#d32ce6', '#f59e0b', '#fff'];
            else if (r.includes('restricted') || r.includes('purple')) colors = ['#8847ff', '#f59e0b', '#fff'];
            else if (r.includes('mil-spec') || r.includes('blue')) colors = ['#4b69ff', '#f59e0b'];
            else if (r.includes('industrial')) colors = ['#5e98d9', '#fff'];

            count = count || (r.includes('covert') || r.includes('classified') || r.includes('extraordinary') ? 30 : 16);

            for (let i = 0; i < count; i++) {
                const pt = document.createElement('div');
                pt.className = 'pt';
                pt.style.setProperty('--px', (Math.random() - 0.5) * 200 + 'px');
                pt.style.setProperty('--py', -(Math.random() * 150 + 20) + 'px');
                pt.style.background = colors[Math.floor(Math.random() * colors.length)];
                pt.style.left = (40 + Math.random() * 20) + '%';
                pt.style.top = (40 + Math.random() * 20) + '%';
                pt.style.animationDelay = Math.random() * 0.2 + 's';
                pt.style.width = (2 + Math.random() * 4) + 'px';
                pt.style.height = pt.style.width;
                pt.style.borderRadius = Math.random() > 0.5 ? '50%' : '2px';
                burst.appendChild(pt);
            }

            setTimeout(() => burst.remove(), 1500);
        }

        // ===== ФУНКЦИИ ДЛЯ ОБЫЧНЫХ КЕЙСОВ (СКРОЛЛЫ) =====
        function animateSingleScroll(track) {
            return new Promise((resolve) => {
                const formData = new FormData();
                formData.append('case_name', caseName);
                formData.append('count', '1');
            
                fetch('/web/api/cases/open/multiple', {
                    method: 'POST',
                    body: formData
                }).then(r => r.json()).then(data => {
                    if (!data.success) { resolve(null); return; }
                
                    const targetItem = data.results[0];
                    const items = [];
                    const totalItems = 32;
                    const targetPos = 14;
                
                    for (let i = 0; i < totalItems; i++) {
                        if (i === targetPos) items.push(targetItem);
                        else items.push(caseItems[Math.floor(Math.random() * caseItems.length)]);
                    }
                
                    track.innerHTML = '';
                    items.forEach((item, idx) => {
                        const div = document.createElement('div');
                        div.className = 'scroll-item-full';
                        if (idx === targetPos) div.classList.add('target-item');
                        
                        const color = getRarityColor(item.rarity);
                        div.style.borderColor = color;
                        div.style.borderWidth = '2px';
                        div.style.borderStyle = 'solid';
                    
                        div.innerHTML = `
                            <img src="${item.image_url || '/static/placeholder.png'}" onerror="this.src='/static/placeholder.png'">
                            <div class="scroll-item-name-full" title="${item.name}">${item.name.substring(0, 25)}</div>
                            <div class="scroll-item-rarity-full" style="color: ${color};">${item.rarity}</div>
                        `;
                        track.appendChild(div);
                    });
                
                    const container = track.parentElement;
                    const containerWidth = container.offsetWidth;
                    const dims = getItemDimensions(false);
                    const itemTotalWidth = dims.itemWidth;
                    const targetOffset = (containerWidth / 2) - (itemTotalWidth / 2);
                    const finalPos = -(targetPos * itemTotalWidth) + targetOffset;
                
                    let currentPos = containerWidth + 100;
                    track.style.transform = `translateX(${currentPos}px)`;
                    track.style.willChange = 'transform';
                    
                    // Speed lines
                    const speedLines = addSpeedLines(container);
                    const duration = 7500;
                    const startTime = performance.now();
                    
                    // Звук прокрутки: тик на каждом предмете
                    let lastTickIndex = -1;
                    
                    function animate() {
                        const now = performance.now();
                        const elapsed = now - startTime;
                        const progress = Math.min(elapsed / duration, 1);
                        const easeOut = 1 - Math.pow(1 - progress, 3);
                        
                        const prevPos = currentPos;
                        currentPos = (containerWidth + 100) - ((containerWidth + 100) - finalPos) * easeOut;
                        track.style.transform = `translateX(${currentPos}px)`;
                        
                        // Звук: определяем какой предмет сейчас в центре
                        const centerX = -currentPos + targetOffset + itemTotalWidth / 2;
                        const tickIndex = Math.floor(centerX / itemTotalWidth);
                        if (tickIndex >= 0 && tickIndex < totalItems && tickIndex !== lastTickIndex) {
                            SoundManager.wheelSpin();
                            lastTickIndex = tickIndex;
                        }
                    
                        if (progress < 1) {
                            requestAnimationFrame(animate);
                        } else {
                            track.style.transform = `translateX(${finalPos}px)`;
                            track.style.willChange = 'auto';
                            removeSpeedLines(speedLines);
                            
                            // Финальный звук
                            const hasRare = ['Covert', 'Extraordinary', 'Rare Special Item'].includes(targetItem.rarity);
                            const hasMid = ['Classified', 'Restricted'].includes(targetItem.rarity);
                            if (hasRare) SoundManager.caseCovert();
                            else if (hasMid) SoundManager.caseRare();
                            
                            // Flash burst
                            flashBurst(container, targetItem.rarity);
                            particleBurst(container, targetItem.rarity, 24);
                            
                            const targetElement = track.querySelector('.target-item');
                            if (targetElement) {
                                targetElement.style.transition = 'all 0.3s ease';
                                targetElement.style.transform = 'scale(1.08)';
                                targetElement.style.boxShadow = `0 0 40px ${getRarityColor(targetItem.rarity)}, 0 0 80px ${getRarityColor(targetItem.rarity)}40`;
                                targetElement.style.zIndex = '100';
                                targetElement.style.borderWidth = '3px';
                            }
                            
                            setTimeout(() => resolve(data), 800);
                        }
                    }
                    
                    requestAnimationFrame(animate);
                }).catch((err) => {
                    console.error('Single scroll error:', err);
                    resolve(null);
                });
            });
        }
        
        function animateMiniScroll(track, index, preloadedResult) {
            return new Promise((resolve) => {
                if (preloadedResult) {
                    // Используем предзагруженный результат (оптимизация)
                    doAnimate({ success: true, results: [preloadedResult], new_balance: 0 });
                    return;
                }
                const formData = new FormData();
                formData.append('case_name', caseName);
                formData.append('count', '1');
                fetch('/web/api/cases/open/multiple', {
                    method: 'POST',
                    body: formData
                }).then(r => r.json()).then(data => doAnimate(data)).catch(err => {
                    console.error('Mini scroll error:', err);
                    resolve(null);
                });
                function doAnimate(data) {
                    if (!data || !data.success) { resolve(null); return; }
                
                    const targetItem = data.results[0];
                    const items = [];
                    const totalItems = 28;
                    const targetPos = 11;
                
                    for (let i = 0; i < totalItems; i++) {
                        if (i === targetPos) items.push(targetItem);
                        else items.push(caseItems[Math.floor(Math.random() * caseItems.length)]);
                    }
                
                    track.innerHTML = '';
                    items.forEach((item, idx) => {
                        const div = document.createElement('div');
                        div.className = 'scroll-item-mini';
                        if (idx === targetPos) div.classList.add('target-mini-item');
                        
                        const color = getRarityColor(item.rarity);
                        div.style.borderColor = color;
                        div.style.borderWidth = '2px';
                        div.style.borderStyle = 'solid';
                    
                        div.innerHTML = `
                            <img src="${item.image_url || '/static/placeholder.png'}" onerror="this.src='/static/placeholder.png'">
                            <div class="scroll-item-name-mini" title="${item.name}">${item.name.substring(0, 12)}</div>
                        `;
                        track.appendChild(div);
                    });
                
                    const container = track.parentElement;
                    const containerWidth = container.offsetWidth;
                    const dims = getItemDimensions(true);
                    const itemTotalWidth = dims.itemWidth;
                    const targetOffset = (containerWidth / 2) - (itemTotalWidth / 2);
                    const finalPos = -(targetPos * itemTotalWidth) + targetOffset;
                
                    let currentPos = containerWidth + 50;
                    track.style.transform = `translateX(${currentPos}px)`;
                    track.style.willChange = 'transform';
                    
                    // Staggered start
                    const staggerDelay = (index || 0) * 120;
                    const speedLines = addSpeedLines(container);
                    const duration = 6000 + Math.random() * 1500;
                    const startTime = performance.now() + staggerDelay;
                    let started = false;
                
                    function animate() {
                        const now = performance.now();
                        const elapsed = now - startTime;
                        
                        if (elapsed < 0) {
                            requestAnimationFrame(animate);
                            return;
                        }
                        
                        if (!started) {
                            started = true;
                        }
                        
                        const progress = Math.min(elapsed / duration, 1);
                        const easeOut = 1 - Math.pow(1 - progress, 3);
                        
                        currentPos = (containerWidth + 50) - ((containerWidth + 50) - finalPos) * easeOut;
                        track.style.transform = `translateX(${currentPos}px)`;
                    
                        if (progress < 1) {
                            requestAnimationFrame(animate);
                        } else {
                            track.style.transform = `translateX(${finalPos}px)`;
                            track.style.willChange = 'auto';
                            removeSpeedLines(speedLines);
                            
                            // Effects (lighter for mini)
                            flashBurst(container, targetItem.rarity);
                            particleBurst(container, targetItem.rarity, 10);
                            
                            const targetElement = track.querySelector('.target-mini-item');
                            if (targetElement) {
                                targetElement.style.transition = 'all 0.3s ease';
                                targetElement.style.transform = 'scale(1.1)';
                                targetElement.style.boxShadow = `0 0 25px ${getRarityColor(targetItem.rarity)}`;
                                targetElement.style.zIndex = '100';
                            }
                            
                            setTimeout(() => resolve(data), 400);
                        }
                    }
                    
                    requestAnimationFrame(animate);
                }
            });
        }
        
        function showResults(results) {
            const resultsDiv = document.getElementById('openingResults');
            
            // Звук в зависимости от редкости
            const rarities = results.map(r => r.rarity || '');
            const hasRare = rarities.some(r => r === 'Covert' || r === 'Extraordinary' || r === 'Rare Special Item');
            const hasRestricted = rarities.some(r => r === 'Classified' || r === 'Restricted');
            if (hasRare) {
                SoundManager.caseCovert();
            } else if (hasRestricted) {
                SoundManager.caseRare();
            }
            
            const grouped = {};
            results.forEach((item) => {
                const key = item.name;
                if (!grouped[key]) {
                    grouped[key] = { ...item, count: 1 };
                } else {
                    grouped[key].count++;
                }
            });
            
            let totalValue = results.reduce((sum, item) => sum + (item.price || 100), 0);
            
            let html = `
                <div class="case-results-header">
                    <div class="case-results-title">🎉 Получено (${results.length})</div>
                    <div class="case-results-actions">
                        <button class="btn btn-success btn-sm" onclick="sellAllResults()">
                            💰 Продать всё (${totalValue.toLocaleString()} ₽)
                        </button>
                        <button class="btn btn-outline btn-sm" onclick="resetCaseUI()">↻ Ещё</button>
                    </div>
                </div>
                <div class="results-grid-enhanced" id="resultsGridEnhanced">
            `;
            
            Object.values(grouped).forEach((item, idx) => {
                const color = getRarityColor(item.rarity);
                html += `
                    <div class="result-card-enhanced" style="animation-delay: ${idx * 0.06}s; --glow: ${color};">
                        <div class="result-card-glow" style="background: radial-gradient(ellipse at center, ${color}20, transparent 70%);"></div>
                        <img src="${item.image_url || '/static/placeholder.png'}" onerror="this.src='/static/placeholder.png'">
                        <div class="result-card-body">
                            <div class="result-name-enhanced" title="${item.name}">${item.name}</div>
                            <div class="result-meta-enhanced">
                                <span style="color: ${color};">${item.rarity}</span>
                            </div>
                            <div class="result-footer-enhanced">
                                <span class="result-price-enhanced">${(item.price || 100).toLocaleString()} ₽</span>
                                <button class="btn-sell-result" onclick="sellResultItem(${item.id})">Продать</button>
                            </div>
                        </div>
                        ${item.count > 1 ? `<span class="result-count-badge">x${item.count}</span>` : ''}
                    </div>
                `;
            });
            
            html += `</div>`;
            
            resultsDiv.innerHTML = html;
            resultsDiv.style.display = 'block';
            
            // Stagger appear animation
            document.querySelectorAll('.result-card-enhanced').forEach((card, i) => {
                card.style.animation = 'none';
                card.offsetHeight;
                card.style.animation = `fadeInUp 0.4s ease-out forwards`;
                card.style.animationDelay = `${i * 0.06}s`;
            });
        }
        
        async function sellResultItem(itemId) {
            Notify.confirm('Продать этот предмет?', 'Продажа', async function(confirmed) {
                if (!confirmed) return;
                try {
                    const response = await fetch('/web/api/inventory/items');
                    const items = await response.json();
                    const inventoryItem = items.find(i => i.item_id === itemId);
                    
                    if (!inventoryItem) {
                        Notify.error('Предмет не найден в инвентаре');
                        return;
                    }
                    
                    const formData = new FormData();
                    formData.append('inventory_id', inventoryItem.id);
                    
                    const sellResponse = await fetch('/web/api/inventory/sell', {
                        method: 'POST',
                        body: formData
                    });
                    
                    const data = await sellResponse.json();
                    
                    if (data.success) {
                        Notify.success('Предмет продан за ' + data.sold_price.toFixed(0) + ' ₽');
                        await refreshUserBalance();
                        await refreshInventoryAjax();
                        const cards = document.querySelectorAll('.result-card-enhanced');
                        for (const card of cards) {
                            const btn = card.querySelector('.btn-sell-result');
                            if (btn && btn.getAttribute('onclick')?.includes(itemId)) {
                                card.style.transition = 'all 0.3s ease';
                                card.style.opacity = '0';
                                card.style.transform = 'scale(0.8)';
                                setTimeout(() => card.remove(), 300);
                                break;
                            }
                        }
                    } else {
                        Notify.error(data.error || 'Ошибка при продаже');
                    }
                } catch (error) {
                    Notify.error('Ошибка соединения');
                }
            });
        }

        async function sellAllResults() {
            if (!window.lastOpenedItems || window.lastOpenedItems.length === 0) {
                Notify.error('Нет предметов для продажи');
                return;
            }
            
            const total = window.lastOpenedItems.reduce((sum, i) => sum + (i.price || 100), 0);
            Notify.confirm('Продать все выпавшие предметы за ' + total.toLocaleString() + ' ₽?', 'Продажа', async function(confirmed) {
                if (!confirmed) return;
                try {
                    const response = await fetch('/web/api/inventory/items');
                    const items = await response.json();
                    
                    const inventoryIds = [];
                    for (const resultItem of window.lastOpenedItems) {
                        const invItem = items.find(i => i.item_id === resultItem.id && 
                                                       Math.abs(i.float - resultItem.float) < 0.001);
                        if (invItem) {
                            inventoryIds.push(invItem.id);
                        }
                    }
                    
                    if (inventoryIds.length === 0) {
                        Notify.error('Предметы не найдены в инвентаре');
                        return;
                    }
                    
                    const formData = new FormData();
                    formData.append('inventory_ids', JSON.stringify(inventoryIds));
                    
                    const sellResponse = await fetch('/web/api/inventory/sell/bulk', {
                        method: 'POST',
                        body: formData
                    });
                    
                    const data = await sellResponse.json();

                    if (data.success) {
                        Notify.success('Продано ' + data.sold_count + ' предметов за ' + data.total_received.toFixed(0) + ' ₽');
                        await refreshUserBalance();
                        await refreshInventoryAjax();
                        const resultsDiv = document.getElementById('openingResults');
                        resultsDiv.style.display = 'none';
                        resultsDiv.innerHTML = '';
                        window.lastOpenedItems = [];
                    } else {
                        Notify.error(data.error || 'Ошибка при продаже');
                    }
                } catch (error) {
                    Notify.error('Ошибка соединения');
                }
            });
        }
        
        function filterItems(rarity) {
            document.querySelectorAll('.filter-btn').forEach(btn => btn.classList.remove('active'));
            event.target.classList.add('active');
            document.querySelectorAll('.rarity-section').forEach(section => {
                section.style.display = (rarity === 'all' || section.dataset.rarity === rarity) ? 'block' : 'none';
            });
        }
        
        async function logout() {
            await fetch('/web/api/auth/logout', { method: 'POST' });
            window.location.href = '/';
        }
        
        window.addEventListener('resize', () => {
            if (!isOpening) {
                updatePriceDisplay();
            }
        });
        
        document.addEventListener('DOMContentLoaded', () => {
            initCountButtons();
            updatePriceDisplay();
            initSlotUI();
            // Hide fast button for farm cases
            if (isFarmCase) {
                const fastBtn = document.getElementById('fastOpenButton');
                if (fastBtn) fastBtn.style.display = 'none';
            }
        });
    </script>
    <script src="/static/js/sounds.js"></script>
    <script src="/static/js/websocket.js"></script>
    <script src="/static/js/notifications.js"></script>
    <script src="/static/js/safemode.js"></script>
    <script>
        function handleAchievements(data) {
            if (data && data.achievements_unlocked && Array.isArray(data.achievements_unlocked) && data.achievements_unlocked.length > 0) {
                data.achievements_unlocked.forEach(ach => {
                    const title = ach.title || ach.name || 'Достижение';
                    const reward = ach.reward || '';
                    showAchievementPopup(title, reward);
                });
            }
        }
    </script>
    <script>
        function toggleSound() {
            const enabled = SoundManager.toggle();
            document.getElementById('soundToggle').textContent = enabled ? '🔊' : '🔇';
        }
        document.addEventListener('DOMContentLoaded', () => {
            const btn = document.getElementById('soundToggle');
            if (btn) btn.textContent = localStorage.getItem('sound_enabled') !== 'false' ? '🔊' : '🔇';
        });
    </script>
{% if user %}{% include '_activity_sidebar.html' %}{% endif %}
</body>
</html>