diff --git a/static/css/style.css b/static/css/style.css index 9137fdc..f7b1662 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -3,4487 +3,599 @@ *, *::before, *::after { margin:0; padding:0; box-sizing:border-box; } :root { - --primary: #f59e0b; - --primary-hover: #d97706; - --primary-glow: rgba(245,158,11,0.25); - --success: #10b981; - --danger: #ef4444; - --warning: #f59e0b; - --bg-deep: #08090d; - --bg-dark: #0b0c10; - --bg-card: #13141a; - --bg-surface: #1a1b23; - --bg-elevated: #21222c; - --text: #e8e6e3; - --text-dim: #8a8a9a; - --text-muted: #5a5a6a; - --border: rgba(255,255,255,0.06); - --border-light: rgba(255,255,255,0.1); - - --rarity-consumer: #b0b0b0; - --rarity-industrial: #5e98d9; - --rarity-mil-spec: #4b69ff; - --rarity-restricted: #8847ff; - --rarity-classified: #d32ce6; - --rarity-covert: #eb4b4b; - --rarity-rare-special: #ffd700; - --rarity-extraordinary: #ffd700; - --rarity-contraband: #ffaa00; - - /* backwards compat */ - --primary-color: var(--primary); - --primary-hover: #d97706; - --success-color: var(--success); - --danger-color: var(--danger); - --warning-color: var(--warning); - --bg-dark: var(--bg-deep); - --bg-card: #13141a; - --bg-light: var(--bg-surface); - --text-primary: var(--text); - --text-secondary: var(--text-dim); - --border-color: var(--border); - - --radius-sm: 6px; - --radius-md: 10px; - --radius-lg: 14px; - --radius-xl: 20px; - - --transition: 0.2s cubic-bezier(0.4,0,0.2,1); + --primary: #f59e0b; + --primary-hover: #d97706; + --primary-glow: rgba(245,158,11,0.35); + --primary-subtle: rgba(245,158,11,0.12); + --success: #22c55e; + --danger: #ef4444; + --info: #3b82f6; + --warning: #f59e0b; + --bg-deep: #07080b; + --bg-dark: #0b0d12; + --bg-card: #111318; + --bg-surface: #181b24; + --bg-elevated: #1e2230; + --bg-hover: rgba(255,255,255,0.04); + --text: #e8e6e3; + --text-dim: #9498a8; + --text-muted: #5c6070; + --border: rgba(255,255,255,0.06); + --border-light: rgba(255,255,255,0.10); + --shadow-sm: 0 1px 3px rgba(0,0,0,0.3); + --shadow-md: 0 4px 12px rgba(0,0,0,0.4); + --shadow-lg: 0 8px 32px rgba(0,0,0,0.5); + --shadow-xl: 0 16px 48px rgba(0,0,0,0.6); + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 14px; + --radius-xl: 18px; + --transition: 0.2s cubic-bezier(0.4,0,0.2,1); + --transition-slow: 0.4s cubic-bezier(0.4,0,0.2,1); + --font-display: 'Russo One', sans-serif; + --font-body: 'Rajdhani', sans-serif; + --rarity-consumer: #b0b0b0; + --rarity-industrial: #5e98d9; + --rarity-mil-spec: #4b69ff; + --rarity-restricted: #8847ff; + --rarity-classified: #d32ce6; + --rarity-covert: #eb4b4b; + --rarity-rare-special: #ffd700; + --rarity-extraordinary: #ffd700; + --z-dropdown: 100; + --z-sticky: 200; + --z-overlay: 300; + --z-modal: 400; + --z-toast: 500; + --z-tooltip: 600; } body { - font-family: 'Rajdhani', sans-serif; - background: var(--bg-deep); - color: var(--text); - line-height: 1.6; - min-height: 100vh; - overflow-x: hidden; -} - -h1, h2, h3, h4, h5, h6, .logo, .nav-link, .btn { - font-family: 'Russo One', sans-serif; - letter-spacing: 0.03em; -} - -::selection { background: var(--primary); color: #000; } -::-webkit-scrollbar { width: 5px; } -::-webkit-scrollbar-track { background: transparent; } -::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } -::-webkit-scrollbar-thumb:hover { background: var(--text-muted); } - -.container { - max-width: 1200px; - margin: 0 auto; - padding: 0 20px; - width: 100%; -} - -/* Навигация */ -.navbar { - background: rgba(11,12,16,0.85); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-bottom: 1px solid var(--border); - padding: 0.7rem 0; - position: sticky; - top: 0; - z-index: 100; -} - -.navbar .container { - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - gap: 0.5rem; -} - -.logo { - font-size: 1.2rem; - font-weight: 700; - color: var(--text); - text-decoration: none; - text-transform: uppercase; - letter-spacing: 0.08em; -} - -.logo:hover { - color: var(--primary-color); -} - -.nav-links { - display: flex; - align-items: center; - gap: 0.25rem; - flex-wrap: wrap; -} - -.nav-link { - color: var(--text-secondary); - text-decoration: none; - padding: 0.4rem 0.65rem; - border-radius: 6px; - transition: all 0.2s; - font-size: 0.8rem; - text-transform: uppercase; - letter-spacing: 0.06em; - font-weight: 500; -} - -.nav-link:hover { - color: var(--text-primary); - background: rgba(255,255,255,0.04); -} - -.nav-link.active { - color: #000; - background: var(--primary); - font-weight: 600; - box-shadow: 0 0 12px var(--primary-glow); -} - -.user-balance { - padding: 0.4rem 0.65rem; - background: rgba(0,0,0,0.3); - border: 1px solid rgba(245, 158, 11, 0.2); - border-radius: 6px; - font-weight: 600; - color: var(--primary-color); - font-size: 0.8rem; - font-family: 'Rajdhani', sans-serif; -} - -/* Кнопки */ -.btn { - padding: 0.5rem 1.1rem; - border: none; - border-radius: var(--radius-sm); - font-size: 0.78rem; - font-weight: 600; - cursor: pointer; - text-decoration: none; - display: inline-flex; - align-items: center; - gap: 0.35rem; - transition: all var(--transition); - white-space: nowrap; - text-transform: uppercase; - letter-spacing: 0.06em; - line-height: 1.2; -} - -.btn-primary { - background: linear-gradient(135deg, var(--primary), #d97706); - color: #000; -} - -.btn-primary:hover { - transform: translateY(-1px); - box-shadow: 0 4px 20px var(--primary-glow); -} - -.btn-primary:disabled { - opacity: 0.3; - cursor: not-allowed; - transform: none; - box-shadow: none; -} - -.btn-outline { - background: transparent; - color: var(--text-dim); - border: 1px solid var(--border); -} - -.btn-outline:hover { - color: var(--text-primary); - border-color: rgba(255,255,255,0.12); - background: rgba(255,255,255,0.03); -} - -.btn-large { - padding: 0.65rem 2rem; - font-size: 0.95rem; -} - -.btn-block { - width: 100%; -} - -.btn-fast { - width: 40px; - height: 40px; - padding: 0; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.1rem; - background: rgba(245,158,11,0.1); - border: 1px solid rgba(245,158,11,0.25); - color: #f59e0b; - border-radius: 8px; - cursor: pointer; - transition: background 0.2s, border-color 0.2s, transform 0.15s; - flex-shrink: 0; -} -.btn-fast:hover:not(:disabled) { - background: rgba(245,158,11,0.2); - border-color: rgba(245,158,11,0.4); - transform: scale(1.05); -} -.btn-fast:disabled { - opacity: 0.3; - cursor: not-allowed; -} - -.btn-sm { - padding: 0.25rem 0.65rem; - font-size: 0.7rem; -} - -.btn-success { - background: var(--success-color); - color: #0a0b0e; - border: none; -} - -.btn-success:hover { - background: #059669; - box-shadow: 0 4px 15px rgba(16, 185, 129, 0.25); -} - -/* Главная страница */ -.hero { - padding: 4rem 0; - text-align: center; - position: relative; -} - -.hero::before { - content: ''; - position: absolute; - top: -50%; - left: 50%; - transform: translateX(-50%); - width: 600px; - height: 600px; - background: radial-gradient(circle, rgba(245, 158, 11, 0.04) 0%, transparent 70%); - pointer-events: none; -} - -.hero h1 { - font-size: 3rem; - margin-bottom: 1rem; - background: linear-gradient(135deg, var(--primary-color), #d97706); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - position: relative; -} - -.hero-subtitle { - font-size: 1.25rem; - color: var(--text-secondary); - margin-bottom: 3rem; - position: relative; -} - -.features { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - gap: 1.5rem; - margin: 3rem 0; -} - -.feature-card { - background: var(--bg-card); - padding: 1.75rem 1.5rem; - border-radius: 10px; - text-align: center; - border: 1px solid var(--border-color); - transition: all 0.25s; -} - -.feature-card:hover { - border-color: rgba(245, 158, 11, 0.15); - transform: translateY(-2px); - box-shadow: 0 8px 30px rgba(0,0,0,0.3); -} - -.feature-icon { - font-size: 2.5rem; - margin-bottom: 0.75rem; -} - -.feature-card h3 { - margin-bottom: 0.5rem; - font-size: 0.95rem; - text-transform: uppercase; - letter-spacing: 0.06em; -} - -.feature-card p { - color: var(--text-secondary); - font-size: 0.85rem; -} - -.hero-actions { - display: flex; - gap: 0.75rem; - justify-content: center; - margin-top: 2rem; -} - -/* Карточка профиля */ -.profile-card, -.auth-card, -.page-card { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - border-radius: 10px; - padding: 1.5rem; - backdrop-filter: blur(8px); -} - -.form-input { - width: 100%; - padding: 0.55rem 0.7rem; - background: rgba(0,0,0,0.3); - border: 1px solid var(--border-color); - border-radius: 6px; - color: var(--text-primary); - font-size: 0.9rem; - font-family: 'Rajdhani', sans-serif; - outline: none; - transition: border-color 0.2s; - box-sizing: border-box; -} - -.form-input:focus { - border-color: rgba(245, 158, 11, 0.3); -} - -.form-label { - font-size: 0.8rem; - color: var(--text-secondary); - margin-bottom: 0.3rem; - display: block; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.stat-value { - font-family: 'Russo One', sans-serif; - color: var(--primary-color); -} - -/* Формы авторизации */ -.auth-container { - display: flex; - align-items: center; - justify-content: center; - min-height: calc(100vh - 73px); - padding: 2rem; -} - -.auth-card { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - padding: 2rem; - border-radius: 10px; - width: 100%; - max-width: 400px; - backdrop-filter: blur(8px); -} - -.auth-card h2 { - text-align: center; - margin-bottom: 1.5rem; - font-size: 1.25rem; - text-transform: uppercase; - letter-spacing: 0.06em; -} - -.auth-form { - display: flex; - flex-direction: column; - gap: 1rem; -} - -.form-group { - display: flex; - flex-direction: column; - gap: 0.3rem; -} - -.form-group label { - font-weight: 600; - font-size: 0.8rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-secondary); -} - -.form-group input { - padding: 0.55rem 0.7rem; - background: rgba(0,0,0,0.3); - border: 1px solid var(--border-color); - border-radius: 6px; - color: var(--text-primary); - font-size: 0.9rem; - font-family: 'Rajdhani', sans-serif; - outline: none; - transition: border-color 0.2s; -} - -.form-group input:focus { - border-color: rgba(245, 158, 11, 0.3); -} - -.form-group small { - color: var(--text-secondary); - font-size: 0.75rem; -} - -.error-message { - background: rgba(239, 68, 68, 0.08); - border: 1px solid rgba(239, 68, 68, 0.3); - color: var(--danger-color); - padding: 0.6rem 0.75rem; - border-radius: 6px; - text-align: center; - font-size: 0.85rem; -} - -.auth-footer { - text-align: center; - margin-top: 1.25rem; - color: var(--text-secondary); - font-size: 0.85rem; -} - -.auth-footer a { - color: var(--primary-color); - text-decoration: none; - font-weight: 600; -} - -.auth-footer a:hover { - text-decoration: underline; -} - -/* Профиль */ -.profile-container { - padding: 2rem 0; -} - -.profile-header { - margin-bottom: 2rem; -} - -.profile-header h1 { - font-size: 2rem; - margin-bottom: 0.5rem; - text-transform: uppercase; - letter-spacing: 0.03em; -} - -.profile-subtitle { - color: var(--text-secondary); - font-size: 0.9rem; -} - -.stats-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 1rem; - margin-bottom: 2rem; -} - -.stat-card { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - padding: 1.25rem 1rem; - border-radius: 10px; - text-align: center; - transition: border-color 0.2s; -} - -.stat-card:hover { - border-color: rgba(245, 158, 11, 0.12); -} - -.stat-value { - font-size: 1.75rem; - font-weight: 700; - color: var(--primary-color); - font-family: 'Russo One', sans-serif; -} - -.stat-label { - color: var(--text-secondary); - margin-top: 0.35rem; - font-size: 0.8rem; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.profile-sections { - display: grid; - gap: 2rem; -} - -.section h2 { - margin-bottom: 1rem; - font-size: 1rem; - text-transform: uppercase; - letter-spacing: 0.06em; - color: #c8c6d0; -} - -.items-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - gap: 0.75rem; -} - -.item-card { - background: rgba(14, 15, 19, 0.9); - padding: 0.75rem 0.85rem; - border-radius: 8px; - border-left: 3px solid; - border: 1px solid var(--border-color); - border-left-width: 3px; - transition: border-color 0.2s; -} - -.item-card:hover { - border-color: rgba(255,255,255,0.08); - border-left-width: 4px; -} - -.item-name { - font-weight: 600; - margin-bottom: 0.35rem; - word-break: break-word; - font-size: 0.8rem; -} - -.item-details { - display: flex; - justify-content: space-between; - font-size: 0.7rem; - color: var(--text-secondary); -} - -.history-list { - display: flex; - flex-direction: column; - gap: 0.4rem; -} - -.history-item { - background: rgba(14, 15, 19, 0.9); - border: 1px solid var(--border-color); - padding: 0.75rem 0.85rem; - border-radius: 8px; - display: flex; - align-items: center; - gap: 0.75rem; - transition: border-color 0.2s; -} - -.history-item:hover { - border-color: rgba(255,255,255,0.08); -} - -.history-icon { - font-size: 1.25rem; - flex-shrink: 0; -} - -.history-content { - flex: 1; - min-width: 0; -} - -.history-title { - font-weight: 600; - margin-bottom: 0.2rem; - font-size: 0.85rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.history-meta { - display: flex; - gap: 0.75rem; - font-size: 0.7rem; - color: var(--text-secondary); - flex-wrap: wrap; -} - -.empty-state { - color: var(--text-secondary); - text-align: center; - padding: 2rem; - font-size: 0.85rem; -} - -/* Кейсы */ -.cases-container { - padding: 1.5rem 0; -} - -.cases-container h1 { - font-size: 1.5rem; - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 0.25rem; -} - -.page-subtitle { - color: var(--text-secondary); - margin-bottom: 1.5rem; - font-size: 0.85rem; -} - -.cases-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - gap: 1rem; -} - -.case-card { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - padding: 1.25rem 1rem; - border-radius: 10px; - cursor: pointer; - transition: all 0.25s; -} - -.case-card:hover { - transform: translateY(-3px); - border-color: rgba(245, 158, 11, 0.15); - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3); -} - -.case-icon { - font-size: 2.5rem; - text-align: center; - margin-bottom: 0.75rem; -} - -.case-card h3 { - text-align: center; - margin-bottom: 0.75rem; - font-size: 0.9rem; - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.case-stats { - text-align: center; - color: var(--text-secondary); - margin-bottom: 0.5rem; - font-size: 0.75rem; -} - -.case-rarities { - display: flex; - flex-wrap: wrap; - gap: 0.2rem; - justify-content: center; - margin-bottom: 0.75rem; -} - -.rarity-badge { - padding: 0.2rem 0.4rem; - border-radius: 3px; - font-size: 0.65rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.03em; -} - -/* Модальные окна */ -.modal { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.8); - backdrop-filter: blur(4px); - display: flex; - align-items: center; - justify-content: center; - z-index: 1000; -} - -.modal-content { - background: rgba(20, 21, 26, 0.95); - border: 1px solid var(--border-color); - padding: 1.5rem; - border-radius: 10px; - text-align: center; - min-width: 300px; - max-width: 500px; - backdrop-filter: blur(8px); -} - -.case-animation { - padding: 1.5rem; -} - -.spinner { - width: 40px; - height: 40px; - border: 3px solid rgba(255,255,255,0.06); - border-top-color: var(--primary-color); - border-radius: 50%; - animation: spin 1s linear infinite; - margin: 0 auto 0.75rem; -} - -@keyframes spin { - to { transform: rotate(360deg); } -} - -.case-result, .contract-result { - padding: 0.75rem; -} - -.result-icon { - font-size: 3rem; - margin-bottom: 0.75rem; -} - -.result-title { - font-size: 1.1rem; - font-weight: 700; - margin-bottom: 0.5rem; -} - -.result-item-name { - color: var(--text-secondary); - font-size: 0.85rem; -} - -/* Контракты */ -.contracts-container { - padding: 1.5rem 0; -} - -.contracts-info { - margin-bottom: 1.5rem; -} - -.info-card { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - padding: 1.25rem; - border-radius: 10px; -} - -.info-card h3 { - margin-bottom: 0.75rem; - font-size: 0.95rem; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.info-card ol { - padding-left: 1.25rem; - color: var(--text-secondary); - font-size: 0.85rem; -} - -.info-card li { - margin-bottom: 0.4rem; -} - -.contracts-groups { - display: flex; - flex-direction: column; - gap: 1.5rem; -} - -.contract-group { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - border-radius: 10px; - overflow: hidden; -} - -.group-header { - padding: 1rem 1.25rem; - border-bottom: 1px solid var(--border-color); - display: flex; - justify-content: space-between; - align-items: center; -} - -.group-header h3 { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: 0.85rem; - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.group-type { - padding: 0.2rem 0.45rem; - background: rgba(0,0,0,0.3); - border: 1px solid var(--border-color); - border-radius: 4px; - font-size: 0.7rem; - color: var(--text-secondary); -} - -.group-count { - color: var(--text-secondary); - font-size: 0.8rem; -} - -.group-items { - padding: 0.75rem; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); - gap: 0.4rem; - max-height: 400px; - overflow-y: auto; -} - -.contract-item { - background: rgba(14, 15, 19, 0.9); - border: 1px solid var(--border-color); - padding: 0.6rem 0.75rem; - border-radius: 8px; - display: flex; - align-items: center; - gap: 0.75rem; - cursor: pointer; - transition: all 0.2s; - border: 2px solid transparent; -} - -.contract-item:hover { - background: var(--bg-light); -} - -.contract-item.selected { - border-color: var(--primary-color); - background: rgba(79, 70, 229, 0.1); -} - -.item-checkbox { - width: 20px; - height: 20px; - border: 2px solid var(--border-color); - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; -} - -.contract-item.selected .item-checkbox { - background: var(--primary-color); - border-color: var(--primary-color); -} - -.contract-item.selected .item-checkbox::after { - content: "✓"; - color: white; - font-size: 14px; -} - -.contract-slot { - background: rgba(0, 0, 0, 0.3); - border: 1px solid #8b7355; - border-radius: 4px; - padding: 10px; - min-height: 70px; -} - -#contractScribble { - width: 100%; - padding: 10px; - background: transparent; - border: 1px dashed #8b7355; - color: #d4c5a9; - font-family: 'Brush Script MT', cursive; - font-size: 18px; - text-align: center; - margin-bottom: 15px; - outline: none; -} - -#contractScribble:focus { - border-color: #d4c5a9; -} - -/* Контракт в стиле CS:GO */ -.contract-paper { - background: #1a1a1a; - background-image: - linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), - linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px); - background-size: 20px 20px; - border: 2px solid #8b7355; - border-radius: 4px; - padding: 30px; - position: relative; - box-shadow: - inset 0 0 50px rgba(0, 0, 0, 0.5), - 0 10px 30px rgba(0, 0, 0, 0.5); -} - -.contract-paper::before { - content: ''; - position: absolute; - top: 10px; - left: 10px; - right: 10px; - bottom: 10px; - border: 1px solid rgba(139, 115, 85, 0.3); - pointer-events: none; -} - -.contract-header { - text-align: center; - margin-bottom: 30px; - border-bottom: 2px solid #8b7355; - padding-bottom: 15px; -} - -.contract-header h2 { - color: #d4c5a9; - text-transform: uppercase; - letter-spacing: 3px; - font-size: 24px; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); -} - -.contract-items-grid { - display: grid; - grid-template-columns: repeat(5, 1fr); - gap: 15px; - margin: 30px 0; -} - -.contract-slot.filled { - background: rgba(139, 115, 85, 0.2); - border-color: #d4c5a9; -} - -.contract-slot-content { - font-family: 'Courier New', monospace; - color: #d4c5a9; - font-size: 11px; - line-height: 1.4; - word-break: break-word; -} - -.contract-signature-line { - margin-top: 30px; - border-top: 1px solid #8b7355; - padding-top: 20px; - display: flex; - justify-content: space-between; - align-items: center; -} - -.contract-signature { - font-family: 'Brush Script MT', cursive; - color: #8b7355; - font-size: 20px; -} - -.contract-stamp { - width: 80px; - height: 80px; - border: 3px double #8b7355; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - color: #8b7355; - transform: rotate(-15deg); - opacity: 0; - transition: all 0.5s; -} - -.contract-stamp.active { - opacity: 1; - transform: rotate(-15deg) scale(1.1); -} - -/* GLOW эффекты для редкостей */ -.glow-consumer-grade { box-shadow: 0 0 40px rgba(176, 176, 176, 0.6); } -.glow-industrial-grade { box-shadow: 0 0 40px rgba(94, 152, 217, 0.6); } -.glow-mil-spec, .glow-mil-spec-grade { box-shadow: 0 0 40px rgba(75, 105, 255, 0.6); } -.glow-restricted { box-shadow: 0 0 40px rgba(136, 71, 255, 0.6); } -.glow-classified { box-shadow: 0 0 40px rgba(211, 44, 230, 0.6); } -.glow-covert { box-shadow: 0 0 40px rgba(235, 75, 75, 0.6); } -.glow-rare-special-item, .glow-extraordinary { box-shadow: 0 0 40px rgba(255, 215, 0, 0.6); } - -.item-info { - flex: 1; - min-width: 0; -} - -.item-info .item-name { - font-size: 0.9rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.item-meta { - font-size: 0.8rem; - color: var(--text-secondary); -} - -.group-footer { - padding: 1rem 1.5rem; - border-top: 1px solid var(--border-color); - display: flex; - justify-content: space-between; - align-items: center; -} - -.selected-count { - color: var(--text-secondary); -} - -.empty-state-large { - text-align: center; - padding: 4rem; -} - -.empty-icon { - font-size: 4rem; - margin-bottom: 1rem; -} - -.empty-state-large h3 { - margin-bottom: 0.5rem; -} - -.empty-state-large p { - color: var(--text-secondary); - margin-bottom: 2rem; -} - -/* Редкости */ -.rarity-consumer-grade { border-left-color: var(--rarity-consumer); } -.rarity-industrial-grade { border-left-color: var(--rarity-industrial); } -.rarity-mil-spec, .rarity-mil-spec-grade { border-left-color: var(--rarity-mil-spec); } -.rarity-restricted { border-left-color: var(--rarity-restricted); } -.rarity-classified { border-left-color: var(--rarity-classified); } -.rarity-covert { border-left-color: var(--rarity-covert); } -.rarity-rare-special-item, .rarity-extraordinary { border-left-color: var(--rarity-rare-special); } -.rarity-contraband { border-left-color: var(--rarity-contraband); } - -.rarity-consumer-grade { color: var(--rarity-consumer); } -.rarity-industrial-grade { color: var(--rarity-industrial); } -.rarity-mil-spec, .rarity-mil-spec-grade { color: var(--rarity-mil-spec); } -.rarity-restricted { color: var(--rarity-restricted); } -.rarity-classified { color: var(--rarity-classified); } -.rarity-covert { color: var(--rarity-covert); } -.rarity-rare-special-item, .rarity-extraordinary { color: var(--rarity-rare-special); } - -.rarity-badge.rarity-consumer-grade { background: var(--rarity-consumer); color: black; } -.rarity-badge.rarity-industrial-grade { background: var(--rarity-industrial); color: white; } -.rarity-badge.rarity-mil-spec { background: var(--rarity-mil-spec); color: white; } -.rarity-badge.rarity-restricted { background: var(--rarity-restricted); color: white; } -.rarity-badge.rarity-classified { background: var(--rarity-classified); color: white; } -.rarity-badge.rarity-covert { background: var(--rarity-covert); color: white; } -.rarity-badge.rarity-rare-special-item { background: var(--rarity-rare-special); color: black; } - -/* Инвентарь */ -.inventory-container { - padding: 1.5rem 0; -} - -.inventory-filters { - display: flex; - gap: 0.75rem; - margin-bottom: 1rem; - flex-wrap: wrap; -} - -.filter-select { - padding: 0.4rem 0.7rem; - background: rgba(0,0,0,0.3); - border: 1px solid var(--border-color); - border-radius: 6px; - color: var(--text-primary); - cursor: pointer; - font-family: 'Rajdhani', sans-serif; - font-size: 0.8rem; - outline: none; -} - -.filter-select:focus { - border-color: rgba(245, 158, 11, 0.3); -} - -.inventory-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); - gap: 0.85rem; -} - -.inventory-grid-detailed { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); - gap: 12px; -} - -.inventory-skin-card { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - border-radius: 8px; - padding: 10px; - cursor: pointer; - transition: all 0.25s; - border: 1px solid var(--border-color); - position: relative; -} - -.inventory-skin-card:hover { - border-color: rgba(245, 158, 11, 0.15); -} - -.inventory-item { - background: rgba(20, 21, 26, 0.8); - border: 1px solid var(--border-color); - border-radius: 8px; - overflow: hidden; -} - -.inventory-item-header { - padding: 0.65rem 0.75rem; - border-bottom: 1px solid var(--border-color); - display: flex; - justify-content: space-between; - align-items: center; -} - -.inventory-skin-card.selected { - border-color: var(--primary-color); - box-shadow: 0 0 15px rgba(245, 158, 11, 0.1); -} - -.inventory-skin-card .skin-image-container { - width: 100%; - height: 110px; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 8px; - background: rgba(0,0,0,0.2); - border-radius: 4px; -} - -.inventory-skin-card .skin-image { - max-width: 100%; - max-height: 110px; - object-fit: contain; -} - -.inventory-skin-card .item-checkbox { - position: absolute; - top: 8px; - right: 8px; - width: 20px; - height: 20px; - border: 2px solid var(--border-color); - border-radius: 4px; - background: var(--bg-dark); -} - -.inventory-skin-card.selected .item-checkbox { - background: var(--primary-color); - border-color: var(--primary-color); -} - -.inventory-skin-card.selected .item-checkbox::after { - content: "✓"; - color: white; - font-size: 14px; - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; -} - -.inventory-item-body { - padding: 0.75rem; -} - -.inventory-item-footer { - padding: 0.75rem; - border-top: 1px solid var(--border-color); - font-size: 0.85rem; - color: var(--text-secondary); -} - -.item-type-badge { - padding: 0.25rem 0.5rem; - background: var(--bg-light); - border-radius: 4px; - font-size: 0.75rem; -} - -.skin-info { - font-size: 12px; -} - -.skin-name { - font-weight: 500; - margin-bottom: 4px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.skin-details { - display: flex; - justify-content: space-between; - color: var(--text-secondary); - font-size: 11px; -} - -/* Кейс открытие */ -.case-opening-modal { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.95); - display: flex; - align-items: center; - justify-content: center; - z-index: 1000; - pointer-events: all; -} - -.case-scroll-container { - width: 100%; - max-width: 900px; - height: 280px; - position: relative; - overflow: hidden; - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - border-radius: 12px; - border: 2px solid var(--border-color); - margin: 0 auto; -} - -.case-scroll-track { - display: flex; - position: absolute; - top: 5%; - transform: translateY(50%); - will-change: left; - transition: none; - left: 0; -} - -.scroll-item { - width: 200px; - height: 240px; - margin: 0 10px; - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background: var(--bg-card); - border-radius: 8px; - padding: 15px; - border: 2px solid transparent; - box-sizing: border-box; -} - -.scroll-item img { - width: 140px; - height: 110px; - object-fit: contain; - margin-bottom: 10px; - pointer-events: none; -} - -.scroll-item-name { - font-size: 11px; - text-align: center; - word-break: break-word; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - width: 100%; -} - -.scroll-item-rarity { - font-size: 10px; - margin-top: 5px; - text-align: center; -} - -.case-center-indicator { - position: absolute; - left: 50%; - top: 0; - bottom: 0; - width: 4px; - background: linear-gradient(to bottom, transparent, #ffd700, #ffd700, transparent); - transform: translateX(-50%); - z-index: 10; - box-shadow: 0 0 30px #ffd700; - pointer-events: none; -} - -.case-center-indicator::before, -.case-center-indicator::after { - content: ''; - position: absolute; - left: -8px; - width: 20px; - height: 20px; - background: #ffd700; - clip-path: polygon(50% 0%, 0% 100%, 100% 100%); -} - -.case-center-indicator::before { - top: -2px; - transform: rotate(180deg); -} - -.case-center-indicator::after { - bottom: -2px; -} - -.case-result-display { - margin-top: 20px; - text-align: center; - animation: fadeInUp 0.5s; -} - -.case-card-link { - text-decoration: none; - color: inherit; - display: block; -} - -.case-card-link:hover .case-card { - transform: translateY(-4px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); -} - -/* Карточки предметов */ -.skin-image { - width: 100%; - height: auto; - border-radius: 4px; - margin-bottom: 8px; -} - -.skin-card { - position: relative; - overflow: hidden; - transition: all 0.3s; -} - -.skin-card:hover { - transform: translateY(-2px); -} - -.skin-card .skin-overlay { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: linear-gradient(135deg, transparent 0%, rgba(255, 255, 255, 0.1) 100%); - opacity: 0; - transition: opacity 0.3s; - pointer-events: none; -} - -.skin-card:hover .skin-overlay { - opacity: 1; -} - -/* Анимации */ -@keyframes fadeInUp { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes typewriter { - from { width: 0; } - to { width: 100%; } -} - -@keyframes blink { - 0%, 100% { border-color: transparent; } - 50% { border-color: #d4c5a9; } -} - -.typewriter-text { - overflow: hidden; - border-right: 2px solid #d4c5a9; - white-space: nowrap; - animation: - typewriter 1s steps(40) 1, - blink 0.75s step-end infinite; -} - -/* Модальные окна с запретом закрытия */ -.modal-locked { - pointer-events: all; -} - -.modal-locked .modal-content { - pointer-events: auto; -} - -.modal-loading { - cursor: wait; -} - -.spinner-large { - width: 60px; - height: 60px; - border: 5px solid var(--border-color); - border-top-color: var(--primary-color); - border-radius: 50%; - animation: spin 1s linear infinite; - margin: 20px auto; -} - -/* ===== СТИЛИ ДЛЯ CASE_DETAIL ===== */ -.case-detail-container { - padding: 1rem 0; - width: 100%; - overflow-x: hidden; -} - -.back-link { - color: var(--text-secondary); - text-decoration: none; - display: inline-block; - margin-bottom: 0.75rem; - font-size: 0.9rem; -} - -.back-link:hover { - color: var(--text-primary); -} - -.case-header { - display: flex; - flex-direction: column; - margin-bottom: 1rem; -} - -.case-title-row { - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - gap: 0.75rem; - margin-bottom: 0.75rem; -} - -.case-title-row h1 { - font-size: 1.5rem; - margin: 0; - word-break: break-word; -} - -.case-info-badge { - display: flex; - align-items: center; - gap: 0.75rem; - flex-wrap: wrap; -} - -.case-price-tag { - background: var(--bg-card); - padding: 0.4rem 0.8rem; - border-radius: 8px; - border: 1px solid var(--success-color); - color: var(--success-color); - font-weight: bold; - font-size: 0.9rem; -} - -.case-subtitle { - color: var(--text-secondary); - font-size: 0.85rem; -} - -.opening-controls { - display: flex; - align-items: center; - gap: 0.75rem; - flex-wrap: wrap; - background: var(--bg-card); - padding: 0.75rem 1rem; - border-radius: 12px; -} - -.total-price-display { - font-size: 1rem; - font-weight: bold; - color: var(--success-color); - margin-left: auto; -} - -.total-price-display span { - color: var(--text-secondary); - font-size: 0.8rem; - font-weight: normal; -} - -.count-selector { - display: flex; - align-items: center; - gap: 0.5rem; - flex-wrap: wrap; -} - -.count-selector label { - color: var(--text-secondary); - font-size: 0.85rem; -} - -.count-buttons { - display: flex; - gap: 0.3rem; - flex-wrap: wrap; -} - -.count-btn { - padding: 0.3rem 0.7rem; - background: var(--bg-dark); - border: 1px solid var(--border-color); - color: var(--text-primary); - border-radius: 6px; - cursor: pointer; - font-size: 0.8rem; - transition: all 0.2s; - min-width: 40px; -} - -.count-btn.active { - background: var(--primary-color); - border-color: var(--primary-color); -} - -.case-opening-section { - background: var(--bg-card); - border-radius: 12px; - padding: 1rem; - margin-bottom: 1rem; -} - -.opening-animation-container { - width: 100%; -} - -/* Speed lines overlay for scroll */ -.scroll-speed-lines { - position: absolute; - inset: 0; - z-index: 5; - pointer-events: none; - background: repeating-linear-gradient( - 90deg, - transparent 0px, - rgba(255,255,255,0.015) 2px, - transparent 4px, - transparent 40px - ); - animation: speedLinesMove 0.4s linear infinite; -} - -@keyframes speedLinesMove { - from { transform: translateX(0); } - to { transform: translateX(40px); } -} - -/* Flash overlay on stop */ -.scroll-flash { - position: absolute; - inset: 0; - z-index: 15; - pointer-events: none; - opacity: 0; - transition: opacity 0.1s; - border-radius: 6px; -} - -.scroll-flash.burst { - opacity: 1; -} - -.scroll-flash.gold { - background: radial-gradient(ellipse at center, rgba(255,215,0,0.4) 0%, transparent 70%); -} - -.scroll-flash.blue { - background: radial-gradient(ellipse at center, rgba(75,105,255,0.4) 0%, transparent 70%); -} - -.scroll-flash.purple { - background: radial-gradient(ellipse at center, rgba(136,71,255,0.4) 0%, transparent 70%); -} - -.scroll-flash.pink { - background: radial-gradient(ellipse at center, rgba(211,44,230,0.4) 0%, transparent 70%); -} - -.scroll-flash.red { - background: radial-gradient(ellipse at center, rgba(235,75,75,0.4) 0%, transparent 70%); -} - -/* Particle burst */ -.particle-burst { - position: absolute; - inset: 0; - z-index: 20; - pointer-events: none; - overflow: hidden; -} - -.particle-burst .pt { - position: absolute; - width: 4px; - height: 4px; - border-radius: 50%; - animation: ptFly 0.8s ease-out forwards; -} - -@keyframes ptFly { - 0% { - opacity: 1; - transform: translate(0, 0) scale(1); - } - 100% { - opacity: 0; - transform: translate(var(--px), var(--py)) scale(0); - } -} - -/* Slot machine (3 vertical reels) */ -.slot-machine { - position: relative; - width: 100%; - max-width: 660px; - margin: 0 auto; - padding: 20px 10px 10px; - background: linear-gradient(135deg, #1a1a2e 0%, #0d0d1a 100%); - border-radius: 16px; - border: 2px solid rgba(255,255,255,0.06); - box-shadow: 0 0 60px rgba(0,0,0,0.5), inset 0 0 40px rgba(0,0,0,0.3); -} - -.slot-reels { - display: flex; - justify-content: center; - gap: 8px; - position: relative; - z-index: 2; -} - -.slot-reel { - width: 160px; - height: 240px; - overflow: hidden; - border-radius: 8px; - background: rgba(0,0,0,0.4); - border: 2px solid rgba(255,255,255,0.08); - position: relative; -} - -.slot-track { - display: flex; - flex-direction: column; - will-change: transform; -} - -.slot-item { - width: 100%; - height: 80px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - border-bottom: 1px solid rgba(255,255,255,0.04); - border-left: 3px solid; - box-sizing: border-box; - padding: 4px; - transition: background 0.3s, box-shadow 0.3s; - flex-shrink: 0; -} - -.slot-item img { - width: 50px; - height: 40px; - object-fit: contain; - pointer-events: none; -} - -.slot-item-name { - font-size: 8px; - text-align: center; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - margin-top: 2px; - color: var(--text-secondary); -} - -.slot-item-hit { - background: rgba(255,215,0,0.12); - box-shadow: inset 0 0 20px rgba(255,215,0,0.15); -} - -.slot-win-line { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - width: calc(100% - 40px); - height: 80px; - border: 2px solid rgba(255,215,0,0.5); - border-radius: 6px; - z-index: 5; - pointer-events: none; - box-shadow: 0 0 20px rgba(255,215,0,0.15), inset 0 0 20px rgba(255,215,0,0.05); -} - -.slot-win-line::before, -.slot-win-line::after { - content: ''; - position: absolute; - left: -4px; - width: calc(100% + 8px); - height: 2px; - background: linear-gradient(90deg, transparent, #ffd700, transparent); -} - -.slot-win-line::before { top: -2px; } -.slot-win-line::after { bottom: -2px; } - -.slot-frame-glow { - position: absolute; - inset: -4px; - border-radius: 18px; - border: 3px solid transparent; - z-index: 1; - pointer-events: none; - transition: all 0.8s; -} - -.slot-result-display { - text-align: center; - margin-top: 12px; - position: relative; - z-index: 10; -} - -.slot-win-banner, .slot-lose-banner { - padding: 12px 20px; - border-radius: 10px; -} - -.slot-win-banner { - background: rgba(255,215,0,0.1); - border: 1px solid rgba(255,215,0,0.3); - animation: slotBannerIn 0.5s ease-out; -} - -.slot-lose-banner { - background: rgba(239,68,68,0.08); - border: 1px solid rgba(239,68,68,0.2); - animation: slotBannerIn 0.5s ease-out; -} - -.slot-win-title { - font-family: 'Russo One', sans-serif; - font-size: 1.4rem; - color: #ffd700; - text-shadow: 0 0 20px rgba(255,215,0,0.4); - letter-spacing: 0.06em; -} - -.slot-win-subtitle, .slot-lose-subtitle { - font-size: 0.85rem; - color: var(--text-secondary); - margin-top: 4px; -} - -.slot-lose-title { - font-family: 'Russo One', sans-serif; - font-size: 1.1rem; - color: var(--danger-color); -} - -@keyframes slotBannerIn { - from { opacity: 0; transform: translateY(20px) scale(0.95); } - to { opacity: 1; transform: translateY(0) scale(1); } -} - -/* Slot activation badges */ -.slot-badge { - position: absolute; - top: 2px; - right: 2px; - font-size: 0.6rem; - line-height: 1; - z-index: 5; - pointer-events: none; - filter: drop-shadow(0 0 3px rgba(0,0,0,0.8)); -} -.slot-badge-extra_spin, -.slot-badge-free_spin, -.slot-badge-guaranteed, -.slot-badge-double, -.slot-badge-quintuple { - padding: 1px 3px; - border-radius: 3px; - font-size: 0.55rem; - font-weight: 700; -} -.slot-badge-extra_spin { color: #8b5cf6; } -.slot-badge-free_spin { color: #10b981; } -.slot-badge-guaranteed { color: #3b82f6; } -.slot-badge-double { color: #f59e0b; } -.slot-badge-quintuple { color: #ef4444; } - -/* Slot activation legend */ -.slot-legend { - margin-top: 14px; - padding: 16px; - background: linear-gradient(135deg, rgba(30,28,45,0.98) 0%, rgba(25,23,40,0.98) 100%); - border: 1px solid rgba(255,255,255,0.12); - border-radius: 10px; - position: relative; - overflow: hidden; - box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 4px 24px rgba(0,0,0,0.5); -} -.slot-legend::before { - content: ''; - position: absolute; - top: 0; left: 0; right: 0; - height: 1px; - background: linear-gradient(90deg, transparent, rgba(245,158,11,0.5), transparent); -} -.slot-legend::after { - content: ''; - position: absolute; - bottom: 0; left: 25%; right: 25%; - height: 1px; - background: linear-gradient(90deg, transparent, rgba(245,158,11,0.2), transparent); -} -.slot-legend-header { - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - margin-bottom: 14px; - position: relative; -} -.slot-legend-header::after { - content: ''; - position: absolute; - bottom: -6px; - left: 30%; - right: 30%; - height: 1px; - background: linear-gradient(90deg, transparent, rgba(245,158,11,0.25), transparent); -} -.slot-legend-symbol { - font-size: 0.6rem; - color: rgba(245,158,11,0.4); - letter-spacing: 6px; -} -.slot-legend-label { - font-family: 'Russo One', sans-serif; - font-size: 0.7rem; - color: rgba(245,158,11,0.7); - text-transform: uppercase; - letter-spacing: 0.2em; -} -.slot-legend-grid { - display: grid; - grid-template-columns: repeat(5, 1fr); - gap: 8px; -} -.slot-legend-card { - display: flex; - flex-direction: column; - align-items: center; - gap: 5px; - padding: 12px 4px 10px; - border-radius: 8px; - background: rgba(255,255,255,0.06); - border: 1px solid rgba(255,255,255,0.08); - cursor: default; - transition: background 0.25s, border-color 0.25s, transform 0.2s, box-shadow 0.25s; - position: relative; -} -.slot-legend-card:hover { - background: rgba(255,255,255,0.1); - border-color: rgba(255,255,255,0.18); - transform: translateY(-3px); - box-shadow: 0 4px 16px rgba(0,0,0,0.4); -} -.slot-legend-card[data-act="extra_spin"] { - background: rgba(139,92,246,0.1); - border-color: rgba(139,92,246,0.18); -} -.slot-legend-card[data-act="extra_spin"]:hover { - background: rgba(139,92,246,0.18); - border-color: rgba(139,92,246,0.3); - box-shadow: 0 4px 20px rgba(139,92,246,0.2); -} -.slot-legend-card[data-act="double"] { - background: rgba(245,158,11,0.1); - border-color: rgba(245,158,11,0.18); -} -.slot-legend-card[data-act="double"]:hover { - background: rgba(245,158,11,0.18); - border-color: rgba(245,158,11,0.3); - box-shadow: 0 4px 20px rgba(245,158,11,0.2); -} -.slot-legend-card[data-act="quintuple"] { - background: rgba(239,68,68,0.1); - border-color: rgba(239,68,68,0.18); -} -.slot-legend-card[data-act="quintuple"]:hover { - background: rgba(239,68,68,0.18); - border-color: rgba(239,68,68,0.3); - box-shadow: 0 4px 20px rgba(239,68,68,0.2); -} -.slot-legend-card[data-act="guaranteed"] { - background: rgba(59,130,246,0.1); - border-color: rgba(59,130,246,0.18); -} -.slot-legend-card[data-act="guaranteed"]:hover { - background: rgba(59,130,246,0.18); - border-color: rgba(59,130,246,0.3); - box-shadow: 0 4px 20px rgba(59,130,246,0.2); -} -.slot-legend-card[data-act="free_spin"] { - background: rgba(16,185,129,0.1); - border-color: rgba(16,185,129,0.18); -} -.slot-legend-card[data-act="free_spin"]:hover { - background: rgba(16,185,129,0.18); - border-color: rgba(16,185,129,0.3); - box-shadow: 0 4px 20px rgba(16,185,129,0.2); -} -.slc-icon { - font-size: 1.1rem; - line-height: 1; - font-family: 'Russo One', sans-serif; - font-weight: 700; - filter: drop-shadow(0 0 8px currentColor); - transition: transform 0.25s, filter 0.25s; -} -.slot-legend-card:hover .slc-icon { - transform: scale(1.2); - filter: drop-shadow(0 0 14px currentColor); -} -.slc-name { - font-family: 'Russo One', sans-serif; - font-size: 0.6rem; - color: #fff; - text-transform: uppercase; - letter-spacing: 0.08em; - white-space: nowrap; - transition: color 0.2s; -} -.slc-desc { - font-family: 'Rajdhani', sans-serif; - font-size: 0.6rem; - color: rgba(255,255,255,0.5); - text-align: center; - line-height: 1.2; - transition: color 0.25s; -} -.slot-legend-card:hover .slc-desc { - color: rgba(255,255,255,0.75); -} - -/* Slot machine style frame */ -.scroll-container-full { - position: relative; - width: 100%; - height: 220px; - max-height: 220px; - overflow: hidden; - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - border-radius: 8px; - border: 2px solid var(--border-color); - box-shadow: - inset 0 0 60px rgba(0,0,0,0.4), - 0 0 30px rgba(0,0,0,0.3); -} - -.scroll-container-full::before { - content: ''; - position: absolute; - top: 0; left: 0; right: 0; - height: 30px; - background: linear-gradient(to bottom, rgba(0,0,0,0.7), transparent); - z-index: 8; - pointer-events: none; -} - -.scroll-container-full::after { - content: ''; - position: absolute; - bottom: 0; left: 0; right: 0; - height: 30px; - background: linear-gradient(to top, rgba(0,0,0,0.7), transparent); - z-index: 8; - pointer-events: none; -} - -/* Target highlight ring */ -.target-highlight-ring { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - width: 130px; - height: 200px; - border: 2px solid transparent; - border-radius: 10px; - z-index: 9; - pointer-events: none; - transition: all 0.3s; -} - -.target-highlight-ring.glow { - border-color: #ffd700; - box-shadow: 0 0 30px rgba(255,215,0,0.3), inset 0 0 30px rgba(255,215,0,0.1); -} - -.scroll-track-full { - display: flex; - position: absolute; - top: 0; - left: 0; - height: 100%; - will-change: transform; - transform: translateZ(0); - backface-visibility: hidden; -} - -.scroll-item-full { - width: 120px; - height: 190px; - margin: 8px 8px; - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: center; - background: var(--bg-card); - border-radius: 8px; - padding: 8px 4px; - border: 2px solid transparent; - box-sizing: border-box; -} - -.scroll-item-full img { - width: 80px; - height: 70px; - object-fit: contain; -} - -.scroll-item-name-full { - font-size: 9px; - text-align: center; - margin-top: 4px; - word-break: break-word; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - width: 100%; -} - -.scroll-item-rarity-full { - font-size: 8px; - margin-top: 3px; - font-weight: bold; -} - -.center-indicator-full { - position: absolute; - left: 50%; - top: 0; - bottom: 0; - width: 3px; - background: linear-gradient(to bottom, transparent, #ffd700, #ffd700, transparent); - transform: translateX(-50%); - z-index: 10; - box-shadow: 0 0 20px #ffd700; - pointer-events: none; -} - -/* МНОЖЕСТВЕННЫЕ СКРОЛЛЫ */ -.multi-scroll-grid { - display: grid; - gap: 0.75rem; - width: 100%; -} - -.scroll-wrapper-full { - width: 100%; - text-align: center; -} - -.scroll-container-mini { - width: 100%; - height: 150px; - max-height: 150px; - position: relative; - overflow: hidden; - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - border-radius: 8px; - border: 2px solid var(--border-color); - box-shadow: - inset 0 0 30px rgba(0,0,0,0.3), - 0 0 15px rgba(0,0,0,0.2); -} - -.scroll-container-mini::before { - content: ''; - position: absolute; - top: 0; left: 0; right: 0; - height: 20px; - background: linear-gradient(to bottom, rgba(0,0,0,0.6), transparent); - z-index: 8; - pointer-events: none; -} - -.scroll-container-mini::after { - content: ''; - position: absolute; - bottom: 0; left: 0; right: 0; - height: 20px; - background: linear-gradient(to top, rgba(0,0,0,0.6), transparent); - z-index: 8; - pointer-events: none; -} - -.mini-target-ring { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - width: 80px; - height: 140px; - border: 2px solid transparent; - border-radius: 6px; - z-index: 9; - pointer-events: none; - transition: all 0.3s; -} - -.mini-target-ring.glow { - border-color: #ffd700; - box-shadow: 0 0 20px rgba(255,215,0,0.25), inset 0 0 20px rgba(255,215,0,0.08); -} - -.scroll-track-mini { - display: flex; - position: absolute; - top: 0; - left: 0; - height: 100%; - will-change: transform; - transform: translateZ(0); -} - -.scroll-item-mini { - width: 70px; - height: 130px; - margin: 6px 6px; - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: center; - background: var(--bg-card); - border-radius: 6px; - padding: 5px 3px; - border: 2px solid transparent; - box-sizing: border-box; -} - -.scroll-item-mini img { - width: 45px; - height: 45px; - object-fit: contain; -} - -.scroll-item-name-mini { - font-size: 7px; - text-align: center; - margin-top: 3px; - word-break: break-word; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; -} - -.center-indicator-mini { - position: absolute; - left: 50%; - top: 0; - bottom: 0; - width: 2px; - background: #ffd700; - transform: translateX(-50%); - z-index: 10; - box-shadow: 0 0 15px #ffd700; - pointer-events: none; -} - -.scroll-label { - margin-top: 0.3rem; - font-size: 0.7rem; - color: var(--text-secondary); -} - -/* Результаты */ -.results-grid-compact { - display: flex; - flex-wrap: wrap; - gap: 0.4rem; - margin-top: 0.75rem; -} - -.result-item-compact { - background: var(--bg-dark); - padding: 0.4rem; - border-radius: 6px; - display: flex; - align-items: center; - gap: 0.4rem; - border-left: 3px solid; - flex: 1 0 auto; - min-width: 160px; -} - -.result-item-compact img { - width: 35px; - height: 30px; - object-fit: contain; -} - -/* Enhanced result cards */ -.case-results-header { - display: flex; - justify-content: space-between; - align-items: center; - flex-wrap: wrap; - gap: 0.5rem; - margin-bottom: 0.75rem; -} - -.case-results-title { - font-family: 'Russo One', sans-serif; - font-size: 1rem; - text-transform: uppercase; - letter-spacing: 0.03em; -} - -.case-results-actions { - display: flex; - gap: 0.4rem; -} - -.results-grid-enhanced { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); - gap: 0.5rem; -} - -.result-card-enhanced { - background: var(--bg-dark); - border-radius: 8px; - overflow: hidden; - position: relative; - border: 1px solid var(--border-color); - transition: all 0.25s; - opacity: 0; - animation: fadeInUp 0.4s ease-out forwards; -} - -.result-card-enhanced:hover { - transform: translateY(-2px); - border-color: var(--glow, var(--primary-color)); - box-shadow: 0 4px 16px rgba(0,0,0,0.3); -} - -.result-card-glow { - position: absolute; - inset: 0; - opacity: 0.3; - pointer-events: none; -} - -.result-card-enhanced img { - width: 100%; - height: 70px; - object-fit: contain; - padding: 0.5rem 0.5rem 0; - display: block; - position: relative; - z-index: 1; -} - -.result-card-body { - padding: 0.35rem 0.5rem 0.4rem; - position: relative; - z-index: 1; -} - -.result-name-enhanced { - font-size: 0.65rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin-bottom: 0.1rem; -} - -.result-meta-enhanced { - font-size: 0.55rem; - color: var(--text-secondary); - margin-bottom: 0.25rem; -} - -.result-footer-enhanced { - display: flex; - justify-content: space-between; - align-items: center; -} - -.result-price-enhanced { - font-size: 0.75rem; - color: var(--success-color); - font-weight: bold; -} - -.result-count-badge { - position: absolute; - top: 4px; - right: 4px; - background: var(--primary-color); - color: white; - border-radius: 50%; - width: 18px; - height: 18px; - display: flex; - align-items: center; - justify-content: center; - font-size: 9px; - font-weight: bold; - z-index: 2; -} - -.result-info-compact { - flex: 1; - min-width: 0; -} - -.result-name-compact { - font-size: 10px; - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.result-meta-compact { - display: flex; - gap: 0.5rem; - font-size: 9px; - color: var(--text-secondary); - flex-wrap: wrap; -} - -.result-count-badge { - background: var(--primary-color); - color: white; - border-radius: 50%; - width: 18px; - height: 18px; - display: flex; - align-items: center; - justify-content: center; - font-size: 9px; - font-weight: bold; - margin-left: 3px; -} - -.btn-sell-result { - padding: 2px 6px; - background: transparent; - border: 1px solid var(--danger-color); - color: var(--danger-color); - border-radius: 4px; - cursor: pointer; - font-size: 8px; -} - -.btn-sell-result:hover { - background: var(--danger-color); - color: white; -} - -/* Список предметов в кейсе */ -.case-items-section { - margin-top: 1rem; -} - -.case-items-section h2 { - font-size: 1.2rem; - margin-bottom: 0.75rem; -} - -.rarity-filters { - display: flex; - flex-wrap: wrap; - gap: 0.3rem; - margin-bottom: 0.75rem; -} - -.filter-btn { - padding: 0.25rem 0.6rem; - background: var(--bg-card); - border: 1px solid var(--border-color); - color: var(--text-secondary); - border-radius: 20px; - cursor: pointer; - font-size: 0.7rem; - transition: all 0.2s; -} - -.filter-btn.active { - background: var(--primary-color); - color: white; - border-color: var(--primary-color); -} - -.filter-btn:hover { - background: var(--bg-light); -} - -.rarity-section { - margin-bottom: 0.75rem; -} - -.rarity-section h3 { - font-size: 0.9rem; - margin-bottom: 0.4rem; - padding-bottom: 0.2rem; - border-bottom: 2px solid; - display: flex; - align-items: center; - gap: 0.4rem; -} - -.rarity-count { - font-size: 0.7rem; - color: var(--text-secondary); - font-weight: normal; -} - -.items-grid-compact { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); - gap: 0.4rem; -} - -.item-card-compact { - background: var(--bg-card); - border-radius: 6px; - padding: 0.4rem; - border-left: 3px solid; - cursor: pointer; - transition: all 0.2s; -} - -.item-card-compact:hover { - transform: translateY(-1px); - background: var(--bg-light); -} - -.item-card-compact img { - width: 100%; - height: 60px; - object-fit: contain; - margin-bottom: 0.2rem; -} - -.item-name-compact { - font-size: 9px; - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin-bottom: 0.2rem; -} - -.item-meta-compact { - display: flex; - justify-content: space-between; - font-size: 8px; - color: var(--text-secondary); - flex-wrap: wrap; -} - -.item-price-compact { - font-size: 9px; - font-weight: bold; - color: var(--success-color); - margin-top: 0.2rem; -} - -/* ===== СТИЛИ ДЛЯ UPGRADE ===== */ -.upgrade-container { - padding: 0.75rem 0; - width: 100%; - overflow-x: hidden; -} - -.upgrade-header { - text-align: center; - margin-bottom: 1rem; -} - -.upgrade-header h1 { - font-size: 1.5rem; - background: linear-gradient(135deg, #ffd700, #ff6b6b); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - margin-bottom: 0.25rem; -} - -.upgrade-header p { - font-size: 0.85rem; - color: var(--text-secondary); -} - -.upgrade-layout { - display: grid; - grid-template-columns: 280px 1fr 280px; - gap: 1rem; - margin-bottom: 1.5rem; -} - -.inventory-panel, .target-panel { - background: var(--bg-card); - border-radius: 12px; - border: 1px solid var(--border-color); - display: flex; - flex-direction: column; - max-height: 500px; -} - -.panel-header, .target-header { - padding: 0.75rem; - border-bottom: 1px solid var(--border-color); - background: var(--bg-card); - border-radius: 12px 12px 0 0; -} - -.panel-title { - font-size: 0.95rem; - font-weight: 600; - display: flex; - justify-content: space-between; - align-items: center; -} - -.inventory-list, .target-list { - flex: 1; - overflow-y: auto; - padding: 0.4rem; - display: flex; - flex-direction: column; - gap: 0.4rem; -} - -.inventory-item-card, .target-item-card { - background: var(--bg-dark); - border-radius: 8px; - padding: 0.5rem; - display: flex; - align-items: center; - gap: 0.5rem; - cursor: pointer; - border: 2px solid transparent; - transition: all 0.2s; -} - -.inventory-item-card:hover, .target-item-card:hover { - background: var(--bg-light); - border-color: var(--primary-color); -} - -.inventory-item-card.selected, .target-item-card.selected { - border-color: #ffd700; - background: rgba(255, 215, 0, 0.1); - box-shadow: 0 0 15px rgba(255, 215, 0, 0.2); -} - -.inventory-item-card.disabled, .target-item-card.disabled { - opacity: 0.5; - cursor: not-allowed; - pointer-events: none; -} - -.inventory-item-card img, .target-item-card img { - width: 45px; - height: 40px; - object-fit: contain; - background: var(--bg-card); - border-radius: 4px; - padding: 3px; -} - -.inventory-item-info, .target-item-info { - flex: 1; - min-width: 0; -} - -.inventory-item-name, .target-item-name { - font-size: 0.75rem; - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin-bottom: 0.15rem; -} - -.inventory-item-meta, .target-item-meta { - display: flex; - justify-content: space-between; - font-size: 0.65rem; - color: var(--text-secondary); -} - -.inventory-item-price, .target-item-price { - color: var(--success-color); - font-weight: bold; -} - -.wheel-panel { - background: var(--bg-card); - border-radius: 12px; - padding: 1rem; - border: 1px solid var(--border-color); - display: flex; - flex-direction: column; - align-items: center; -} - -.selected-items-display { - display: flex; - align-items: center; - justify-content: center; - gap: 0.5rem; - margin-bottom: 0.75rem; - width: 100%; -} - -.selected-item-mini { - text-align: center; - flex: 1; - min-width: 0; -} - -.selected-item-mini img { - width: 60px; - height: 50px; - object-fit: contain; - background: var(--bg-dark); - border-radius: 6px; - padding: 5px; -} - -.selected-item-mini-name { - font-size: 0.65rem; - margin-top: 0.2rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.selected-item-mini-price { - font-size: 0.7rem; - color: var(--success-color); - font-weight: bold; -} - -.arrow-icon { - font-size: 1.2rem; - color: var(--primary-color); -} - -.wheel-container { - position: relative; - width: 220px; - height: 220px; - margin: 0.5rem 0; -} - -.wheel { - width: 100%; - height: 100%; - border-radius: 50%; - background: conic-gradient( - from 0deg, - #10b981 0deg, - #10b981 calc(var(--probability) * 3.6deg / 2), - #2d1b1b calc(var(--probability) * 3.6deg / 2), - #2d1b1b calc(360deg - var(--probability) * 3.6deg / 2), - #10b981 calc(360deg - var(--probability) * 3.6deg / 2), - #10b981 360deg - ); - border: 3px solid var(--border-color); - box-shadow: 0 0 30px rgba(0,0,0,0.5); -} - -.wheel-pointer { - position: absolute; - top: -10px; - left: 50%; - transform: translateX(-50%); - width: 0; - height: 0; - border-left: 12px solid transparent; - border-right: 12px solid transparent; - border-top: 24px solid #ffd700; - filter: drop-shadow(0 0 6px #ffd700); - z-index: 10; -} - -.wheel-center { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 40px; - height: 40px; - background: var(--bg-card); - border-radius: 50%; - border: 2px solid #ffd700; - display: flex; - align-items: center; - justify-content: center; - font-weight: bold; - font-size: 0.8rem; - color: #ffd700; - z-index: 5; -} - -.upgrade-actions { - display: flex; - align-items: center; - gap: 0.5rem; - margin-top: 0.5rem; -} - -.upgrade-btn { - padding: 0.6rem 1.5rem; - font-size: 1rem; - flex: 1; -} - -.quick-btn { - width: 38px; - height: 38px; - border-radius: 8px; - border: 1px solid var(--border-color); - background: var(--bg-dark); - color: var(--text-secondary); - font-size: 1.1rem; - cursor: pointer; - transition: all 0.2s; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.quick-btn:hover { - border-color: var(--primary-color); - color: var(--primary-color); -} - -.quick-btn.active { - background: var(--primary-color); - color: #fff; - border-color: var(--primary-color); - box-shadow: 0 0 12px rgba(245, 158, 11, 0.4); -} - -.inv-filter-bar { - display: flex; - gap: 0.3rem; - align-items: center; - margin-top: 0.4rem; -} - -.inv-search-input { - flex: 1; - padding: 0.35rem 0.5rem; - background: var(--bg-dark); - border: 1px solid var(--border-color); - border-radius: 5px; - color: var(--text-primary); - font-size: 0.75rem; - min-width: 0; -} - -.inv-search-input:focus { - outline: none; - border-color: var(--primary-color); -} - -.inv-sort-group { - display: flex; - gap: 2px; - flex-shrink: 0; -} - -.inv-sort-btn { - padding: 0.3rem 0.4rem; - background: var(--bg-dark); - border: 1px solid var(--border-color); - color: var(--text-secondary); - border-radius: 4px; - cursor: pointer; - font-size: 0.7rem; - transition: all 0.15s; - line-height: 1; -} - -.inv-sort-btn.active { - background: var(--primary-color); - color: white; - border-color: var(--primary-color); -} - -.inv-sort-btn:hover { - border-color: var(--primary-color); -} - -.target-search-input { - width: 100%; - padding: 0.5rem; - background: var(--bg-dark); - border: 1px solid var(--border-color); - border-radius: 6px; - color: var(--text-primary); - margin-bottom: 0.4rem; - font-size: 0.85rem; -} - -.target-search-input:focus { - outline: none; - border-color: var(--primary-color); -} - -.sort-controls { - display: flex; - gap: 0.3rem; -} - -.sort-btn { - flex: 1; - padding: 0.3rem; - background: var(--bg-dark); - border: 1px solid var(--border-color); - color: var(--text-secondary); - border-radius: 4px; - cursor: pointer; - font-size: 0.65rem; -} - -.sort-btn.active { - background: var(--primary-color); - color: white; - border-color: var(--primary-color); -} - -/* История апгрейдов */ -.history-section { - background: var(--bg-card); - border-radius: 12px; - padding: 1rem; - border: 1px solid var(--border-color); -} - -.history-title { - font-size: 1rem; - margin-bottom: 0.75rem; - display: flex; - align-items: center; - gap: 0.4rem; -} - -.history-count { - font-size: 0.65rem; - color: var(--text-secondary); - background: var(--bg-dark); - padding: 0.1rem 0.45rem; - border-radius: 10px; - font-weight: normal; -} - -.history-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); - gap: 0.5rem; -} - -.history-card { - background: var(--bg-dark); - border-radius: 8px; - padding: 0.4rem 0.5rem; - display: flex; - align-items: center; - gap: 0.4rem; - transition: all 0.2s; -} - -.history-card:hover { - background: var(--bg-light); -} - -.history-card.success { - border-left: 3px solid #10b981; -} - -.history-card.fail { - border-left: 3px solid #ef4444; -} - -.history-card img { - width: 36px; - height: 30px; - object-fit: contain; - flex-shrink: 0; -} - -.history-info { - flex: 1; - min-width: 0; -} - -.history-names { - font-size: 0.7rem; - margin-bottom: 0.15rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.history-meta { - display: flex; - justify-content: space-between; - font-size: 0.6rem; - color: var(--text-secondary); -} - -.history-result { - font-weight: bold; -} - -.history-result.success { - color: #10b981; -} - -.history-result.fail { - color: #ef4444; -} - -/* ===== СТИЛИ ДЛЯ CASES ===== */ -.cases-sections { - display: flex; - flex-direction: column; - gap: 1.5rem; -} - -.section-tab { - font-size: 1.2rem; - margin-bottom: 0.75rem; - padding-bottom: 0.4rem; - border-bottom: 2px solid var(--primary-color); - display: inline-block; -} - -.section-cases { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); - gap: 1rem; -} - -.case-card-new { - background: var(--bg-card); - border-radius: 10px; - overflow: hidden; - transition: all 0.3s; - text-decoration: none; - color: inherit; - display: block; - border: 1px solid var(--border-color); -} - -.case-card-new:hover { - transform: translateY(-4px); - box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4); - border-color: var(--primary-color); -} - -.case-image { - width: 100%; - height: 120px; - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - display: flex; - align-items: center; - justify-content: center; - position: relative; -} - -.case-image img { - max-width: 70%; - max-height: 90px; - object-fit: contain; -} - -.case-price-badge { - position: absolute; - top: 8px; - right: 8px; - background: var(--bg-dark); - padding: 0.2rem 0.5rem; - border-radius: 20px; - font-size: 0.75rem; - font-weight: bold; - color: var(--success-color); - border: 1px solid var(--success-color); -} - -.case-info { - padding: 0.75rem; -} - -.case-title { - font-size: 0.95rem; - font-weight: 600; - margin-bottom: 0.3rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.case-description { - font-size: 0.75rem; - color: var(--text-secondary); - margin-bottom: 0.5rem; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; -} - -.case-stats { - display: flex; - justify-content: space-between; - font-size: 0.7rem; - color: var(--text-secondary); - margin-bottom: 0.5rem; -} - -.case-rarities-mini { - display: flex; - gap: 0.2rem; - flex-wrap: wrap; -} - -.rarity-dot { - width: 8px; - height: 8px; - border-radius: 50%; -} - -.case-footer { - display: flex; - align-items: center; - justify-content: space-between; - padding-top: 0.5rem; - border-top: 1px solid var(--border-color); -} - -.case-price { - font-weight: bold; - color: var(--success-color); - font-size: 0.85rem; -} - -.btn-open { - padding: 0.3rem 0.8rem; - background: var(--primary-color); - color: white; - border: none; - border-radius: 5px; - cursor: pointer; - font-size: 0.75rem; -} - -.btn-open:hover { - background: var(--primary-hover); -} - -/* ===== АДАПТИВНОСТЬ ===== */ -@media (max-width: 1000px) { - .upgrade-layout { - grid-template-columns: 1fr; - gap: 0.75rem; - } - - .inventory-panel, .target-panel { - max-height: 350px; - } - - .wheel-container { - width: 200px; - height: 200px; - } -} - -@media (max-width: 768px) { - .container { - padding: 0 12px; - } - - .navbar .container { - flex-direction: column; - align-items: stretch; - } - - .logo { - text-align: center; - } - - .nav-links { - justify-content: center; - gap: 0.25rem; - } - - .nav-link { - padding: 0.4rem 0.5rem; - font-size: 0.8rem; - } - - .user-balance { - font-size: 0.8rem; - padding: 0.4rem 0.5rem; - } - - .hero h1 { - font-size: 2rem; - } - - .hero-subtitle { - font-size: 1rem; - } - - .btn { - padding: 0.4rem 0.8rem; - font-size: 0.85rem; - } - - .btn-large { - padding: 0.6rem 1.2rem; - } - - /* Кейсы */ - .case-title-row h1 { - font-size: 1.2rem; - } - - .opening-controls { - flex-direction: column; - align-items: stretch; - } - - .total-price-display { - margin-left: 0; - text-align: center; - } - - .count-selector { - justify-content: center; - } - - .count-buttons { - justify-content: center; - } - - .scroll-container-full { - height: 190px; - } - - .scroll-item-full { - width: 100px; - height: 165px; - margin: 5px 5px; - } - - .scroll-item-full img { - width: 65px; - height: 55px; - } - - .scroll-container-mini { - height: 130px; - } - - .scroll-item-mini { - width: 60px; - height: 115px; - margin: 4px 4px; - } - - .scroll-item-mini img { - width: 40px; - height: 40px; - } - - .items-grid-compact { - grid-template-columns: repeat(3, 1fr); - } - - .multi-scroll-grid { - grid-template-columns: repeat(2, 1fr) !important; - } - - /* Контракты */ - .contract-items-grid { - grid-template-columns: repeat(2, 1fr); - } - - .case-scroll-container { - height: 250px; - } - - .scroll-item { - width: 150px; - height: 200px; - } - - .scroll-item img { - width: 100px; - height: 80px; - } - - .stats-grid { - grid-template-columns: repeat(2, 1fr); - } - - .cases-grid { - grid-template-columns: 1fr; - } - - .group-items { - grid-template-columns: 1fr; - } - - .group-header { - flex-direction: column; - gap: 0.5rem; - text-align: center; - } - - .group-footer { - flex-direction: column; - gap: 1rem; - } - - .section-cases { - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 0.75rem; - } - - .case-image { - height: 100px; - } - - .case-title { - font-size: 0.85rem; - } - - .case-description { - font-size: 0.7rem; - } -} - -@media (max-width: 480px) { - .nav-links { - flex-wrap: wrap; - justify-content: center; - } - - .nav-link { - font-size: 0.75rem; - padding: 0.3rem 0.4rem; - } - - .hero h1 { - font-size: 1.5rem; - } - - /* Кейсы */ - .case-title-row { - flex-direction: column; - align-items: flex-start; - } - - .scroll-container-full { - height: 170px; - } - - .scroll-item-full { - width: 90px; - height: 150px; - } - - .scroll-item-full img { - width: 55px; - height: 45px; - } - - .scroll-item-name-full { - font-size: 8px; - } - - .scroll-container-mini { - height: 115px; - } - - .scroll-item-mini { - width: 55px; - height: 100px; - } - - .items-grid-compact { - grid-template-columns: repeat(2, 1fr); - } - - .result-item-compact { - min-width: 130px; - } - - /* Апгрейд */ - .upgrade-header h1 { - font-size: 1.3rem; - } - - .wheel-container { - width: 180px; - height: 180px; - } - - .wheel-center { - width: 35px; - height: 35px; - font-size: 0.7rem; - } - - .selected-item-mini img { - width: 50px; - height: 40px; - } - - .history-grid { - grid-template-columns: 1fr; - } - - /* Кейсы */ - .cases-container h1 { - font-size: 1.3rem; - } - - .section-cases { - grid-template-columns: 1fr 1fr; - } - - .case-image { - height: 90px; - } - - .case-info { - padding: 0.5rem; - } -} - -/* Общие мобильные фиксы */ -@media (max-width: 768px) { - body { - font-size: 14px; - } - - input, button, select, textarea { - font-size: 16px !important; - } - - html, body { - max-width: 100%; - overflow-x: hidden; - } - - img { - max-width: 100%; - height: auto; - } -} - -/* ===== АПГРЕЙД — РЕДИЗАЙН ===== */ - -body { - font-family: 'Rajdhani', sans-serif; -} - -h1, h2, h3, h4, h5, h6, .logo, .nav-link, .btn { - font-family: 'Rajdhani', sans-serif; -} - -.upgrade-page { - font-family: 'Rajdhani', sans-serif; - background: radial-gradient(ellipse at 50% 0%, #14161f 0%, #0a0b0e 100%); + font-family: var(--font-body); + background: var(--bg-deep); + color: var(--text); + line-height: 1.6; min-height: 100vh; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; } -.upgrade-page .upgrade-header h1 { - font-family: 'Russo One', sans-serif; - font-size: 1.75rem; - letter-spacing: 0.05em; - text-transform: uppercase; - background: linear-gradient(135deg, #f59e0b 0%, #d97706 50%, #f59e0b 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - text-shadow: none; - filter: drop-shadow(0 0 20px rgba(245, 158, 11, 0.3)); - margin-bottom: 0.25rem; -} - -.upgrade-page .upgrade-header p { - color: #8a8a9a; - font-size: 0.9rem; +h1, h2, h3, h4, h5, h6, .logo, .nav-link, .btn, .display-font { + font-family: var(--font-display); letter-spacing: 0.03em; } -.upgrade-page .upgrade-layout { - display: grid; - grid-template-columns: 280px 1fr 280px; - gap: 1rem; - margin-bottom: 1.5rem; -} +::selection { background: var(--primary); color: #000; } +::-webkit-scrollbar { width: 5px; height: 5px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 3px; } +::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.2); } -.upgrade-page .panel-title { - font-family: 'Russo One', sans-serif; - font-size: 0.8rem; - letter-spacing: 0.08em; - text-transform: uppercase; - color: #c8c6d0; -} +.container { max-width: 1200px; margin: 0 auto; padding: 0 20px; width: 100%; } -/* Панели */ -.upgrade-page .inventory-panel, -.upgrade-page .target-panel { - background: rgba(20, 21, 26, 0.8); - backdrop-filter: blur(8px); - border-radius: 10px; - border: 1px solid rgba(255, 255, 255, 0.06); - display: flex; - flex-direction: column; - max-height: 520px; - overflow: hidden; -} - -.upgrade-page .panel-header, -.upgrade-page .target-header { - padding: 0.65rem 0.75rem; - border-bottom: 1px solid rgba(255, 255, 255, 0.06); - flex-shrink: 0; -} - -.upgrade-page .inventory-list, -.upgrade-page .target-list { - flex: 1; - overflow-y: auto; - padding: 0.4rem; - display: flex; - flex-direction: column; - gap: 0.35rem; -} - -.upgrade-page .inventory-list::-webkit-scrollbar, -.upgrade-page .target-list::-webkit-scrollbar { - width: 4px; -} - -.upgrade-page .inventory-list::-webkit-scrollbar-track, -.upgrade-page .target-list::-webkit-scrollbar-track { - background: transparent; -} - -.upgrade-page .inventory-list::-webkit-scrollbar-thumb, -.upgrade-page .target-list::-webkit-scrollbar-thumb { - background: rgba(245, 158, 11, 0.3); - border-radius: 2px; -} - -/* Карточки предметов */ -.upgrade-page .inventory-item-card, -.upgrade-page .target-item-card { - background: rgba(14, 15, 19, 0.9); - border-radius: 8px; - padding: 0.45rem 0.5rem; - display: flex; - align-items: center; - gap: 0.5rem; - cursor: pointer; - border: 1px solid rgba(255, 255, 255, 0.04); - transition: all 0.2s ease; - position: relative; -} - -.upgrade-page .inventory-item-card::before, -.upgrade-page .target-item-card::before { - content: ''; - position: absolute; - left: 0; - top: 4px; - bottom: 4px; - width: 2px; - border-radius: 1px; - background: rgba(255, 255, 255, 0.08); - transition: all 0.2s ease; -} - -.upgrade-page .inventory-item-card:hover, -.upgrade-page .target-item-card:hover { - border-color: rgba(245, 158, 11, 0.2); - background: rgba(20, 21, 26, 0.9); -} - -.upgrade-page .inventory-item-card:hover::before, -.upgrade-page .target-item-card:hover::before { - background: rgba(245, 158, 11, 0.4); - width: 3px; -} - -.upgrade-page .inventory-item-card.selected { - border-color: rgba(245, 158, 11, 0.5); - background: rgba(245, 158, 11, 0.06); - box-shadow: 0 0 20px rgba(245, 158, 11, 0.08), inset 0 0 20px rgba(245, 158, 11, 0.03); -} - -.upgrade-page .inventory-item-card.selected::before { - background: #f59e0b; - width: 3px; - box-shadow: 0 0 8px rgba(245, 158, 11, 0.6); -} - -.upgrade-page .inventory-item-card.disabled, -.upgrade-page .target-item-card.disabled { - opacity: 0.35; - cursor: not-allowed; - pointer-events: none; -} - -.upgrade-page .inventory-item-card img, -.upgrade-page .target-item-card img { - width: 42px; - height: 36px; - object-fit: contain; - background: rgba(0, 0, 0, 0.3); - border-radius: 4px; - padding: 2px; - flex-shrink: 0; -} - -.upgrade-page .inventory-item-name, -.upgrade-page .target-item-name { - font-size: 0.72rem; - font-weight: 600; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - color: #d4d2d8; - letter-spacing: 0.01em; -} - -.upgrade-page .inventory-item-meta, -.upgrade-page .target-item-meta { - display: flex; - justify-content: space-between; - font-size: 0.6rem; - color: #6b6b7a; - margin-top: 0.1rem; -} - -.upgrade-page .inventory-item-price, -.upgrade-page .target-item-price { - color: #f59e0b; - font-weight: 700; - font-size: 0.65rem; -} - -/* Сортировка и поиск */ -.upgrade-page .target-search-input { - width: 100%; - padding: 0.45rem 0.6rem; - background: rgba(0, 0, 0, 0.4); - border: 1px solid rgba(255, 255, 255, 0.06); - border-radius: 6px; - color: #e0dde8; - font-size: 0.8rem; - font-family: 'Rajdhani', sans-serif; - outline: none; - transition: border-color 0.2s; - box-sizing: border-box; -} - -.upgrade-page .target-search-input:focus { - border-color: rgba(245, 158, 11, 0.4); -} - -.upgrade-page .sort-controls { - display: flex; - gap: 0.3rem; - margin-top: 0.4rem; -} - -.upgrade-page .sort-btn { - flex: 1; - padding: 0.25rem 0.3rem; - background: rgba(0, 0, 0, 0.3); - border: 1px solid rgba(255, 255, 255, 0.04); - border-radius: 4px; - color: #6b6b7a; - font-size: 0.6rem; - font-family: 'Rajdhani', sans-serif; - font-weight: 600; - cursor: pointer; - transition: all 0.15s; - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.upgrade-page .sort-btn:hover { - color: #c8c6d0; - border-color: rgba(255, 255, 255, 0.1); -} - -.upgrade-page .sort-btn.active { - color: #f59e0b; - border-color: rgba(245, 158, 11, 0.3); - background: rgba(245, 158, 11, 0.08); -} - -/* Центральная панель — Колесо */ -.upgrade-page .wheel-panel { - background: rgba(20, 21, 26, 0.8); - backdrop-filter: blur(8px); - border-radius: 10px; - border: 1px solid rgba(255, 255, 255, 0.06); - padding: 1.25rem 1rem; - display: flex; - flex-direction: column; - align-items: center; -} - -.upgrade-page .selected-items-display { - display: flex; - align-items: center; - justify-content: center; - gap: 0.75rem; - margin-bottom: 0.75rem; - width: 100%; -} - -.upgrade-page .selected-item-mini { - text-align: center; - flex: 1; - min-width: 0; -} - -.upgrade-page .selected-item-mini .item-frame { - width: 64px; - height: 52px; - margin: 0 auto; - background: rgba(0, 0, 0, 0.4); - border-radius: 6px; - border: 1px solid rgba(255, 255, 255, 0.06); - display: flex; - align-items: center; - justify-content: center; - padding: 4px; - transition: all 0.3s; -} - -.upgrade-page .selected-item-mini.selected .item-frame { - border-color: rgba(245, 158, 11, 0.4); - box-shadow: 0 0 15px rgba(245, 158, 11, 0.1); -} - -.upgrade-page .selected-item-mini img { - width: 100%; - height: 100%; - object-fit: contain; -} - -.upgrade-page .selected-item-mini-name { - font-size: 0.62rem; - margin-top: 0.25rem; - color: #8a8a9a; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.upgrade-page .selected-item-mini-price { - font-size: 0.7rem; - color: #f59e0b; - font-weight: 700; - font-family: 'Rajdhani', sans-serif; -} - -.upgrade-page .arrow-icon { - font-size: 1rem; - color: #4a4a5a; - flex-shrink: 0; - opacity: 0.5; -} - -/* Колесо */ -.upgrade-page .wheel-container { - position: relative; - width: 280px; - height: 280px; - margin: 0.25rem 0 0.5rem; -} - -.upgrade-page .wheel-outer-ring { - position: absolute; - inset: -8px; - border-radius: 50%; - background: conic-gradient( - from 0deg, - rgba(245, 158, 11, 0.08), - rgba(245, 158, 11, 0.02) 25%, - rgba(245, 158, 11, 0.08) 50%, - rgba(245, 158, 11, 0.02) 75%, - rgba(245, 158, 11, 0.08) 100% - ); - border: 1px solid rgba(245, 158, 11, 0.15); -} - -.upgrade-page .wheel { - width: 100%; - height: 100%; - border-radius: 50%; - background: conic-gradient( - from calc(180deg - var(--probability, 0) * 3.6deg / 2), - #10b981 0deg, - #10b981 calc(var(--probability, 0) * 3.6deg), - #2d1b1b calc(var(--probability, 0) * 3.6deg), - #2d1b1b 360deg - ); - border: 2px solid rgba(255, 255, 255, 0.08); - box-shadow: - 0 0 40px rgba(0, 0, 0, 0.6), - inset 0 0 30px rgba(0, 0, 0, 0.4); - position: relative; - z-index: 1; -} - -.upgrade-page .wheel::after { - content: ''; - position: absolute; - inset: 4px; - border-radius: 50%; - border: 1px solid rgba(255, 255, 255, 0.04); -} - -/* Tick marks */ -.upgrade-page .wheel-ticks { - position: absolute; - inset: -4px; - border-radius: 50%; - z-index: 2; - pointer-events: none; -} - -.upgrade-page .wheel-ticks::before { - content: ''; - position: absolute; - inset: 2px; - border-radius: 50%; - background: repeating-conic-gradient( - from 0deg, - transparent 0deg, - transparent 2deg, - rgba(255, 255, 255, 0.06) 2deg, - rgba(255, 255, 255, 0.06) 3deg - ); -} - -/* Pointer container — вращается вокруг колеса */ -.upgrade-page .wheel-pointer-container { - position: absolute; +/* ── Navbar ── */ +.navbar { + background: rgba(7,8,11,0.92); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border-bottom: 1px solid var(--border); + padding: 0.6rem 0; + position: sticky; top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 10; - pointer-events: none; - transform-origin: center center; + z-index: var(--z-sticky); } - -/* Pointer */ -.upgrade-page .wheel-pointer { - position: absolute; - top: -14px; - left: 50%; - transform: translateX(-50%); - width: 0; - height: 0; - border-left: 10px solid transparent; - border-right: 10px solid transparent; - border-top: 24px solid #f59e0b; - filter: drop-shadow(0 0 10px rgba(245, 158, 11, 0.6)) drop-shadow(0 0 20px rgba(245, 158, 11, 0.3)); +.navbar .container { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; } +.logo { + font-size: 1.15rem; font-weight: 700; color: var(--text); + text-decoration: none; text-transform: uppercase; letter-spacing: 0.08em; + display: flex; align-items: center; gap: 0.4rem; white-space: nowrap; } - -.upgrade-page .wheel-pointer::after { - content: ''; - position: absolute; - top: -28px; - left: -4px; - width: 8px; - height: 8px; - background: #f59e0b; - border-radius: 50%; - box-shadow: 0 0 12px rgba(245, 158, 11, 0.8); +.logo span { color: var(--primary); } +.logo:hover { opacity: 0.85; } +.nav-links { display: flex; align-items: center; gap: 0.15rem; flex-wrap: wrap; } +.nav-link { + color: var(--text-dim); text-decoration: none; + padding: 0.4rem 0.7rem; border-radius: var(--radius-sm); + transition: all var(--transition); font-size: 0.78rem; + text-transform: uppercase; letter-spacing: 0.06em; font-weight: 500; + white-space: nowrap; position: relative; } - -/* Center hub */ -.upgrade-page .wheel-center { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 52px; - height: 52px; - background: radial-gradient(circle at 40% 35%, #1e1f2a, #0a0b0e); - border-radius: 50%; - border: 2px solid rgba(245, 158, 11, 0.3); - display: flex; - align-items: center; - justify-content: center; - font-weight: 700; - font-size: 0.85rem; - color: #f59e0b; - z-index: 5; - font-family: 'Russo One', sans-serif; - box-shadow: - 0 0 20px rgba(245, 158, 11, 0.1), - inset 0 0 15px rgba(0, 0, 0, 0.5); - letter-spacing: 0.02em; +.nav-link::after { + content: ''; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%) scaleX(0); + width: 60%; height: 2px; background: var(--primary); border-radius: 1px; + transition: transform var(--transition); } - - - -/* Кнопка апгрейда */ -.upgrade-page .upgrade-btn { - padding: 0.65rem 2.5rem; - font-family: 'Russo One', sans-serif; - font-size: 0.85rem; - text-transform: uppercase; - letter-spacing: 0.1em; - background: linear-gradient(135deg, #f59e0b, #d97706); - color: #0a0b0e; - border: none; - border-radius: 6px; - cursor: pointer; - transition: all 0.25s; - position: relative; - overflow: hidden; - margin-top: 0.25rem; -} - -.upgrade-page .upgrade-btn:hover:not(:disabled) { - transform: translateY(-1px); - box-shadow: 0 4px 20px rgba(245, 158, 11, 0.3); -} - -.upgrade-page .upgrade-btn:active:not(:disabled) { - transform: translateY(0); -} - -.upgrade-page .upgrade-btn:disabled { - opacity: 0.3; - cursor: not-allowed; -} - -.upgrade-page .upgrade-btn::after { - content: ''; - position: absolute; - inset: 0; - background: linear-gradient(135deg, transparent 40%, rgba(255,255,255,0.15) 50%, transparent 60%); - transition: transform 0.4s; - transform: translateX(-100%); -} - -.upgrade-page .upgrade-btn:hover:not(:disabled)::after { - transform: translateX(100%); -} - -/* Результат */ -/* Toast */ -.toast-container { - position: fixed; - top: 70px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - display: flex; - flex-direction: column; - gap: 0.4rem; - pointer-events: none; -} - -.toast { - padding: 0.5rem 1rem; - border-radius: 8px; - font-size: 0.8rem; - font-weight: 600; - white-space: nowrap; - opacity: 0; - transform: translateY(-10px); - transition: all 0.3s cubic-bezier(0.2, 0.9, 0.3, 1.2); - pointer-events: auto; - background: var(--bg-card); - border: 1px solid var(--border-color); - color: var(--text-primary); - box-shadow: 0 4px 20px rgba(0,0,0,0.5); -} - -.toast.show { - opacity: 1; - transform: translateY(0); -} - -.toast.success { - border-color: #10b981; - box-shadow: 0 4px 20px rgba(16,185,129,0.3); -} - -.toast.fail { - border-color: #ef4444; - box-shadow: 0 4px 20px rgba(239,68,68,0.2); -} - -.upgrade-page .result-item-display img { - width: 72px; - height: 60px; - object-fit: contain; - animation: resultItemSlide 0.5s ease; -} - -.upgrade-page .result-item-display span { - font-size: 0.65rem; - color: #8a8a9a; - text-align: center; - max-width: 180px; -} - -@keyframes resultFadeIn { - from { opacity: 0; } - to { opacity: 1; } -} - -@keyframes resultPulse { - 0% { transform: scale(0.5); opacity: 0; } - 60% { transform: scale(1.15); } - 100% { transform: scale(1); opacity: 1; } -} - -@keyframes resultItemSlide { - from { transform: translateY(20px); opacity: 0; } - to { transform: translateY(0); opacity: 1; } -} - -/* Win sparkles */ -.upgrade-page .sparkle-container { - position: absolute; - inset: 0; - pointer-events: none; - z-index: 25; - overflow: hidden; - border-radius: 10px; -} - -.upgrade-page .sparkle { - position: absolute; - width: 4px; - height: 4px; - background: #f59e0b; - border-radius: 50%; - animation: sparkleFloat 1.5s ease-out forwards; -} - -@keyframes sparkleFloat { - 0% { - transform: translate(0, 0) scale(1); - opacity: 1; - } - 100% { - transform: translate(var(--dx, 50px), var(--dy, -80px)) scale(0); - opacity: 0; - } -} - -/* История */ -.upgrade-page .history-section { - margin-top: 0.5rem; -} - -.upgrade-page .history-title { - font-family: 'Russo One', sans-serif; - font-size: 0.85rem; - letter-spacing: 0.06em; - text-transform: uppercase; - color: #6b6b7a; - margin-bottom: 0.6rem; -} - -.upgrade-page .history-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); - gap: 0.5rem; -} - -.upgrade-page .history-card { - background: rgba(20, 21, 26, 0.6); - border-radius: 8px; - padding: 0.5rem 0.6rem; - display: flex; - align-items: center; - gap: 0.5rem; - border: 1px solid rgba(255, 255, 255, 0.04); - transition: border-color 0.2s; -} - -.upgrade-page .history-card:hover { - border-color: rgba(255, 255, 255, 0.08); -} - -.upgrade-page .history-card.success { - border-left: 3px solid rgba(16, 185, 129, 0.5); -} - -.upgrade-page .history-card.fail { - border-left: 3px solid rgba(239, 68, 68, 0.4); -} - -.upgrade-page .history-card img { - width: 36px; - height: 30px; - object-fit: contain; - background: rgba(0, 0, 0, 0.3); - border-radius: 4px; - padding: 2px; - flex-shrink: 0; -} - -.upgrade-page .history-info { - flex: 1; - min-width: 0; -} - -.upgrade-page .history-names { - font-size: 0.68rem; - color: #b0aeb8; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.upgrade-page .history-meta { - display: flex; - justify-content: space-between; - font-size: 0.6rem; - color: #6b6b7a; - margin-top: 0.1rem; -} - -.upgrade-page .history-result.success { - color: #10b981; - font-weight: 600; -} - -.upgrade-page .history-result.fail { - color: #ef4444; - font-weight: 600; -} - -/* Быстрые фильтры цены */ -.upgrade-page .price-filter-bar { - display: flex; - gap: 0.25rem; - margin-top: 0.4rem; - flex-wrap: wrap; -} - -.upgrade-page .pf-btn { - padding: 0.2rem 0.45rem; - background: rgba(0, 0, 0, 0.3); - border: 1px solid rgba(255, 255, 255, 0.04); - border-radius: 4px; - color: #6b6b7a; - font-size: 0.6rem; - font-family: 'Rajdhani', sans-serif; - font-weight: 600; - cursor: pointer; - transition: all 0.15s; - text-transform: uppercase; - letter-spacing: 0.03em; -} - -.upgrade-page .pf-btn:hover { - color: #c8c6d0; - border-color: rgba(255, 255, 255, 0.1); -} - -.upgrade-page .pf-btn.active { - color: #f59e0b; - border-color: rgba(245, 158, 11, 0.3); - background: rgba(245, 158, 11, 0.08); -} - -/* Пустое состояние */ -.upgrade-page .empty-state { - text-align: center; - padding: 1.5rem 0.5rem; - color: #4a4a5a; - font-size: 0.8rem; -} - -/* Адаптивность */ -@media (max-width: 1000px) { - .upgrade-page .upgrade-layout { - grid-template-columns: 1fr; - gap: 0.75rem; - } - .upgrade-page .inventory-panel, - .upgrade-page .target-panel { - max-height: 320px; - } - .upgrade-page .wheel-container { - width: 240px; - height: 240px; - } +.nav-link:hover { color: var(--text); background: var(--bg-hover); } +.nav-link:hover::after { transform: translateX(-50%) scaleX(1); } +.nav-link.active { color: #000; background: var(--primary); font-weight: 600; } +.nav-link.active::after { display: none; } +.user-balance { + padding: 0.35rem 0.7rem; background: rgba(0,0,0,0.3); + border: 1px solid rgba(245,158,11,0.25); border-radius: var(--radius-sm); + font-weight: 600; color: var(--primary); font-size: 0.8rem; + font-family: var(--font-body); white-space: nowrap; + display: flex; align-items: center; gap: 0.3rem; } +.user-balance::before { content: '⟠'; font-size: 0.7rem; } +.mobile-toggle { display: none; background: none; border: none; color: var(--text); font-size: 1.3rem; cursor: pointer; padding: 0.3rem; } @media (max-width: 768px) { - .upgrade-page .upgrade-header h1 { - font-size: 1.3rem; - } - .upgrade-page .wheel-container { - width: 200px; - height: 200px; - } - .upgrade-page .wheel-center { - width: 44px; - height: 44px; - font-size: 0.7rem; - } - .upgrade-page .selected-item-mini .item-frame { - width: 52px; - height: 42px; - } - .upgrade-page .history-grid { - grid-template-columns: 1fr; + .mobile-toggle { display: block; } + .nav-links { + display: none; position: absolute; top: 100%; left: 0; right: 0; + background: rgba(7,8,11,0.98); backdrop-filter: blur(16px); + flex-direction: column; padding: 0.5rem; border-bottom: 1px solid var(--border); + gap: 0.15rem; z-index: var(--z-dropdown); } + .nav-links.open { display: flex; } + .nav-link { width: 100%; padding: 0.6rem 0.8rem; } + .nav-links .btn, .nav-links .user-balance { width: 100%; justify-content: center; } + .navbar .container { position: relative; } } -/* ===== Дополнительные стили для скролла ===== */ -.scroll-item-sm.target-item { - transition: all 0.3s ease; - z-index: 100; -} - -.mini-scroll-item-sm.target-mini-item { - transition: all 0.3s ease; - z-index: 100; -} - -.scroll-item-sm.target-item[style*="border-color"] { - box-shadow: 0 0 30px currentColor; -} - -.mini-scroll-item-sm.target-mini-item[style*="border-color"] { - box-shadow: 0 0 20px currentColor; -} - -.multi-scroll-container { - display: grid; - gap: 1.5rem; - margin: 2rem 0; - justify-content: center; -} - -.scroll-wrapper { - text-align: center; -} - -.mini-scroll-container { - width: 100%; - min-width: 180px; - height: 200px; - position: relative; - overflow: hidden; - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - border-radius: 8px; - border: 2px solid var(--border-color); -} - -.mini-scroll-track { - display: flex; - position: absolute; - top: 0; - left: 0; - height: 100%; - will-change: transform; - transition: filter 0.3s; -} - -.mini-scroll-item { - width: 90px; - height: 180px; - margin: 10px 10px; - flex-shrink: 0; - display: flex; - flex-direction: column; - align-items: center; - background: var(--bg-card); - border-radius: 6px; - padding: 8px 4px; - border: 2px solid transparent; -} - -.mini-scroll-item img { - width: 70px; - height: 70px; - object-fit: contain; -} - -.mini-item-name { - font-size: 9px; - text-align: center; - margin-top: 5px; - word-break: break-word; -} - -.mini-item-rarity { - font-size: 8px; - margin-top: 3px; - font-weight: bold; -} - -.mini-center-indicator { - position: absolute; - left: 50%; - top: 0; - bottom: 0; - width: 3px; - background: linear-gradient(to bottom, transparent, #ffd700, #ffd700, transparent); - transform: translateX(-50%); - z-index: 10; - box-shadow: 0 0 20px #ffd700; - pointer-events: none; -} - -.result-count { - position: absolute; - top: 5px; - right: 5px; - background: var(--primary-color); - color: white; - border-radius: 50%; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - font-size: 12px; - font-weight: bold; -} - -.result-item { - position: relative; -} - -.results-actions { - display: flex; - gap: 1rem; - justify-content: center; - margin-top: 2rem; -} - -/* ====== Всеобщий UI-полироль ====== */ - -/* Плавные скроллбары */ -::-webkit-scrollbar { width: 6px; height: 6px; } -::-webkit-scrollbar-track { background: transparent; } -::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; } -::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.15); } - -/* Стеклянные карточки */ -.glass-card, .card, [class*="panel"] { - background: rgba(20, 21, 26, 0.7); - backdrop-filter: blur(12px); - border: 1px solid var(--border-color); - border-radius: 12px; - transition: border-color 0.2s, box-shadow 0.2s; -} -.glass-card:hover, .card:hover, [class*="panel"]:hover { - border-color: rgba(255,255,255,0.1); -} - -/* Тени для всех модалок */ -.modal, [class*="modal"], [class*="Modal"] { - background: rgba(10, 11, 14, 0.85); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); -} - -/* Плавные переходы для элементов */ -a, button, .btn, .nav-link, .item-card, [class*="btn"] { - transition: all 0.2s ease; -} - -/* Улучшенные кнопки */ +/* ── Buttons ── */ .btn { - position: relative; - overflow: hidden; - border-radius: 8px; - font-weight: 600; - letter-spacing: 0.02em; - cursor: pointer; - border: none; - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.4rem; -} -.btn:active { - transform: scale(0.97); + padding: 0.5rem 1.1rem; border: none; border-radius: var(--radius-sm); + font-size: 0.78rem; font-weight: 600; cursor: pointer; + text-decoration: none; display: inline-flex; align-items: center; + gap: 0.4rem; transition: all var(--transition); white-space: nowrap; + text-transform: uppercase; letter-spacing: 0.06em; line-height: 1.2; + position: relative; overflow: hidden; } +.btn::after { content: ''; position: absolute; inset: 0; background: rgba(255,255,255,0); transition: background var(--transition); } +.btn:hover::after { background: rgba(255,255,255,0.08); } +.btn:active::after { background: rgba(255,255,255,0.12); } .btn-primary { - background: linear-gradient(135deg, var(--primary-color), #f97316); - color: white; + background: linear-gradient(135deg, var(--primary), #d97706); color: #000; + box-shadow: 0 2px 12px var(--primary-glow); } -.btn-primary:hover { - filter: brightness(1.1); - box-shadow: 0 4px 20px rgba(245, 158, 11, 0.3); +.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 4px 20px rgba(245,158,11,0.4); } +.btn-primary:disabled { opacity: 0.35; cursor: not-allowed; transform: none; box-shadow: none; background: var(--text-muted); color: var(--text-dim); } +.btn-outline { + background: transparent; color: var(--text-dim); border: 1px solid var(--border-light); +} +.btn-outline:hover { color: var(--text); border-color: rgba(255,255,255,0.18); background: var(--bg-hover); } +.btn-ghost { background: transparent; color: var(--text-dim); border: none; } +.btn-ghost:hover { color: var(--text); background: var(--bg-hover); } +.btn-success { background: var(--success); color: #000; } +.btn-success:hover { box-shadow: 0 4px 15px rgba(34,197,94,0.3); transform: translateY(-1px); } +.btn-danger { background: var(--danger); color: #fff; } +.btn-danger:hover { box-shadow: 0 4px 15px rgba(239,68,68,0.3); transform: translateY(-1px); } +.btn-large { padding: 0.65rem 2rem; font-size: 0.9rem; } +.btn-sm { padding: 0.3rem 0.65rem; font-size: 0.7rem; } +.btn-block { width: 100%; justify-content: center; } +.btn-icon { + width: 36px; height: 36px; padding: 0; display: flex; + align-items: center; justify-content: center; font-size: 1rem; + background: var(--primary-subtle); border: 1px solid rgba(245,158,11,0.2); + color: var(--primary); border-radius: var(--radius-sm); cursor: pointer; + transition: all var(--transition); flex-shrink: 0; +} +.btn-icon:hover { background: rgba(245,158,11,0.2); border-color: rgba(245,158,11,0.35); transform: scale(1.05); } +.btn-icon:disabled { opacity: 0.3; cursor: not-allowed; transform: none; } + +/* ── Cards ── */ +.card { + background: var(--bg-card); + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 1.25rem; + transition: all var(--transition); +} +.card:hover { border-color: rgba(255,255,255,0.08); } +.card-hover:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); + border-color: rgba(245,158,11,0.15); +} +.card-glass { + background: rgba(17,19,24,0.7); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid rgba(255,255,255,0.06); +} +.card-glow { position: relative; overflow: hidden; } +.card-glow::before { + content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; + background: conic-gradient(from 0deg, transparent, var(--primary-glow), transparent, transparent); + animation: glowRotate 4s linear infinite; opacity: 0; transition: opacity var(--transition-slow); +} +.card-glow:hover::before { opacity: 1; } +.card-glow > * { position: relative; z-index: 1; } +@keyframes glowRotate { to { transform: rotate(360deg); } } + +/* ── Forms ── */ +.form-group { margin-bottom: 1rem; } +.form-label { + display: block; font-size: 0.8rem; font-weight: 600; color: var(--text-dim); + margin-bottom: 0.35rem; text-transform: uppercase; letter-spacing: 0.05em; +} +.form-input, .form-select, .form-textarea { + width: 100%; padding: 0.55rem 0.8rem; font-size: 0.9rem; + background: var(--bg-dark); border: 1px solid var(--border-light); + border-radius: var(--radius-sm); color: var(--text); + font-family: var(--font-body); transition: border-color var(--transition), box-shadow var(--transition); + outline: none; +} +.form-input:focus, .form-select:focus, .form-textarea:focus { + border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-glow); +} +.form-input::placeholder { color: var(--text-muted); } +.form-error { color: var(--danger); font-size: 0.8rem; margin-top: 0.25rem; } +.form-hint { color: var(--text-muted); font-size: 0.78rem; margin-top: 0.2rem; } +.form-checkbox { + display: flex; align-items: center; gap: 0.5rem; cursor: pointer; + font-size: 0.9rem; +} +.form-checkbox input[type="checkbox"] { + width: 18px; height: 18px; accent-color: var(--primary); cursor: pointer; } -/* Плавный вход для контента */ -main, .container, .crash-layout, .inventory-container { - animation: contentFadeIn 0.3s ease; -} -@keyframes contentFadeIn { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } +/* ── Grids ── */ +.grid { display: grid; gap: 1rem; } +.grid-2 { grid-template-columns: repeat(2, 1fr); } +.grid-3 { grid-template-columns: repeat(3, 1fr); } +.grid-4 { grid-template-columns: repeat(4, 1fr); } +.grid-auto { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); } +.grid-auto-sm { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); } +@media (max-width: 768px) { + .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } } -/* Нормализация отступов */ -main { - padding: 1.5rem 1rem; +/* ── Hero ── */ +.hero { + padding: 4rem 0; text-align: center; + position: relative; overflow: hidden; } -main.container { - padding: 1.5rem 20px; +.hero::before { + content: ''; position: absolute; top: -40%; left: 50%; transform: translateX(-50%); + width: 700px; height: 700px; + background: radial-gradient(circle, rgba(245,158,11,0.05) 0%, transparent 65%); + pointer-events: none; +} +.hero h1 { + font-size: clamp(2rem, 5vw, 3.5rem); margin-bottom: 0.75rem; + background: linear-gradient(135deg, var(--primary), #fbbf24); + -webkit-background-clip: text; -webkit-text-fill-color: transparent; + background-clip: text; position: relative; text-wrap: balance; +} +.hero-subtitle { + font-size: clamp(1rem, 2.5vw, 1.3rem); color: var(--text-dim); + margin-bottom: 2.5rem; position: relative; +} +.hero-actions { display: flex; gap: 0.75rem; justify-content: center; flex-wrap: wrap; } + +/* ── Section ── */ +.section { padding: 2.5rem 0; } +.section-title { + font-size: 1.5rem; margin-bottom: 0.3rem; text-wrap: balance; +} +.section-subtitle { color: var(--text-dim); font-size: 0.95rem; margin-bottom: 1.5rem; } +.section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.25rem; flex-wrap: wrap; gap: 0.75rem; } +.section-tabs { + display: flex; gap: 0.25rem; flex-wrap: wrap; + padding: 0.25rem; background: var(--bg-dark); border-radius: var(--radius-sm); +} +.section-tab { + padding: 0.35rem 0.8rem; border: none; background: transparent; + color: var(--text-dim); font-size: 0.78rem; font-weight: 500; + cursor: pointer; border-radius: 4px; transition: all var(--transition); + font-family: var(--font-body); text-transform: uppercase; letter-spacing: 0.04em; +} +.section-tab:hover { color: var(--text); background: var(--bg-hover); } +.section-tab.active { background: var(--primary); color: #000; font-weight: 600; } + +/* ── Case Card ── */ +.case-card { + background: var(--bg-card); + border: 1px solid var(--border); + border-radius: var(--radius-md); + overflow: hidden; + transition: all var(--transition-slow); + cursor: pointer; + position: relative; +} +.case-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 30px rgba(0,0,0,0.5); + border-color: rgba(245,158,11,0.2); +} +.case-card-image { + width: 100%; aspect-ratio: 1; object-fit: contain; + padding: 1.5rem; background: linear-gradient(135deg, var(--bg-dark) 0%, var(--bg-card) 100%); + display: flex; align-items: center; justify-content: center; + position: relative; +} +.case-card-image img { max-width: 85%; max-height: 85%; transition: transform var(--transition-slow); filter: drop-shadow(0 4px 8px rgba(0,0,0,0.4)); } +.case-card:hover .case-card-image img { transform: scale(1.08) rotate(-3deg); } +.case-card-body { padding: 0.85rem 1rem; } +.case-card-name { font-family: var(--font-display); font-size: 0.9rem; margin-bottom: 0.2rem; } +.case-card-desc { color: var(--text-dim); font-size: 0.8rem; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } +.case-card-footer { + display: flex; align-items: center; justify-content: space-between; + padding: 0.65rem 1rem; border-top: 1px solid var(--border); +} +.case-card-price { + font-family: var(--font-display); font-size: 0.95rem; color: var(--primary); + display: flex; align-items: center; gap: 0.3rem; +} +.case-card-price span { font-size: 0.7rem; color: var(--text-muted); font-family: var(--font-body); } +.case-card-rarity { + display: flex; gap: 3px; +} +.case-card-rarity-dot { + width: 8px; height: 8px; border-radius: 50%; opacity: 0.6; } -/* Улучшенный текст */ -p, span, div, label { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +/* ── Modal ── */ +.modal-overlay { + position: fixed; inset: 0; background: rgba(0,0,0,0.7); + backdrop-filter: blur(4px); z-index: var(--z-overlay); + display: flex; align-items: center; justify-content: center; + animation: fadeIn 0.2s ease; padding: 1rem; +} +@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } +.modal { + background: var(--bg-surface); border: 1px solid var(--border-light); + border-radius: var(--radius-lg); width: 100%; max-width: 500px; + max-height: 90vh; overflow-y: auto; + animation: modalSlideIn 0.25s ease; box-shadow: var(--shadow-xl); +} +@keyframes modalSlideIn { from { transform: translateY(20px) scale(0.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } } +.modal-header { + display: flex; align-items: center; justify-content: space-between; + padding: 1rem 1.25rem; border-bottom: 1px solid var(--border); +} +.modal-title { font-family: var(--font-display); font-size: 1rem; } +.modal-close { + background: none; border: none; color: var(--text-dim); font-size: 1.3rem; + cursor: pointer; padding: 0.2rem; line-height: 1; transition: color var(--transition); +} +.modal-close:hover { color: var(--text); } +.modal-body { padding: 1.25rem; } +.modal-footer { + display: flex; align-items: center; justify-content: flex-end; gap: 0.5rem; + padding: 1rem 1.25rem; border-top: 1px solid var(--border); } -/* Красивые инпуты */ -input, select, textarea { - background: rgba(255,255,255,0.04); - border: 1px solid var(--border-color); - border-radius: 8px; - color: var(--text-primary); - padding: 0.6rem 0.8rem; - font-family: 'Rajdhani', sans-serif; - font-size: 0.95rem; - transition: border-color 0.2s, box-shadow 0.2s; - outline: none; +/* ── Table ── */ +.table-wrap { overflow-x: auto; } +table { + width: 100%; border-collapse: collapse; font-size: 0.85rem; } -input:focus, select:focus, textarea:focus { - border-color: var(--primary-color); - box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.1); +th, td { + padding: 0.6rem 0.8rem; text-align: left; border-bottom: 1px solid var(--border); + white-space: nowrap; } -input::placeholder { - color: var(--text-secondary); - opacity: 0.6; +th { + color: var(--text-dim); font-weight: 600; text-transform: uppercase; + letter-spacing: 0.05em; font-size: 0.72rem; +} +tr:hover td { background: var(--bg-hover); } + +/* ── Badge ── */ +.badge { + display: inline-flex; align-items: center; gap: 0.25rem; + padding: 0.15rem 0.5rem; border-radius: 4px; + font-size: 0.7rem; font-weight: 600; text-transform: uppercase; + letter-spacing: 0.03em; +} +.badge-yellow { background: rgba(245,158,11,0.15); color: var(--primary); } +.badge-green { background: rgba(34,197,94,0.15); color: var(--success); } +.badge-red { background: rgba(239,68,68,0.15); color: var(--danger); } +.badge-blue { background: rgba(59,130,246,0.15); color: var(--info); } +.badge-purple { background: rgba(136,71,255,0.15); color: #a78bfa; } + +/* ── Stats ── */ +.stats-grid { display: grid; gap: 0.75rem; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); } +.stat-card { + background: var(--bg-card); border: 1px solid var(--border); + border-radius: var(--radius-md); padding: 1rem 1.15rem; +} +.stat-value { font-family: var(--font-display); font-size: 1.4rem; color: var(--primary); } +.stat-label { font-size: 0.75rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.04em; margin-top: 0.15rem; } + +/* ── Filters ── */ +.filter-bar { + display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; + padding: 0.75rem; background: var(--bg-dark); border-radius: var(--radius-md); + margin-bottom: 1rem; +} +.filter-bar .form-input { width: auto; min-width: 160px; flex: 1; } +.filter-chip { + padding: 0.25rem 0.65rem; background: transparent; border: 1px solid var(--border-light); + color: var(--text-dim); border-radius: 4px; font-size: 0.75rem; cursor: pointer; + transition: all var(--transition); font-family: var(--font-body); +} +.filter-chip:hover { border-color: rgba(255,255,255,0.2); color: var(--text); } +.filter-chip.active { background: var(--primary-subtle); border-color: var(--primary); color: var(--primary); } + +/* ── Loading ── */ +.spinner { + width: 32px; height: 32px; border: 3px solid var(--border); + border-top-color: var(--primary); border-radius: 50%; + animation: spin 0.7s linear infinite; +} +@keyframes spin { to { transform: rotate(360deg); } } +.spinner-sm { width: 18px; height: 18px; border-width: 2px; } +.loading-dots { display: flex; gap: 4px; align-items: center; } +.loading-dots span { + width: 6px; height: 6px; border-radius: 50%; background: var(--primary); + animation: dotBounce 1.2s ease-in-out infinite; +} +.loading-dots span:nth-child(2) { animation-delay: 0.15s; } +.loading-dots span:nth-child(3) { animation-delay: 0.3s; } +@keyframes dotBounce { 0%,80%,100% { transform: scale(0.5); opacity: 0.5; } 40% { transform: scale(1); opacity: 1; } } + +/* ── Toast / Notification ── */ +.toast-container { + position: fixed; top: 1rem; right: 1rem; z-index: var(--z-toast); + display: flex; flex-direction: column; gap: 0.5rem; pointer-events: none; +} +.toast { + pointer-events: auto; padding: 0.65rem 1rem; border-radius: var(--radius-sm); + background: var(--bg-surface); border: 1px solid var(--border-light); + box-shadow: var(--shadow-lg); font-size: 0.85rem; + display: flex; align-items: center; gap: 0.5rem; + animation: toastIn 0.25s ease; max-width: 360px; +} +@keyframes toastIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } +.toast-success { border-left: 3px solid var(--success); } +.toast-error { border-left: 3px solid var(--danger); } +.toast-info { border-left: 3px solid var(--info); } +.toast-warning { border-left: 3px solid var(--warning); } + +/* ── Empty state ── */ +.empty-state { + text-align: center; padding: 3rem 1rem; color: var(--text-dim); +} +.empty-state-icon { font-size: 2.5rem; margin-bottom: 0.75rem; opacity: 0.5; } +.empty-state-title { font-family: var(--font-display); font-size: 1.1rem; color: var(--text); margin-bottom: 0.3rem; } +.empty-state-desc { font-size: 0.9rem; margin-bottom: 1rem; } + +/* ── Rarity colors ── */ +.rarity-consumer { color: var(--rarity-consumer); } +.rarity-industrial { color: var(--rarity-industrial); } +.rarity-mil-spec { color: var(--rarity-mil-spec); } +.rarity-restricted { color: var(--rarity-restricted); } +.rarity-classified { color: var(--rarity-classified); } +.rarity-covert { color: var(--rarity-covert); } +.rarity-rare-special { color: var(--rarity-rare-special); } +.bg-rarity-consumer { background: rgba(176,176,176,0.12); } +.bg-rarity-industrial { background: rgba(94,152,217,0.12); } +.bg-rarity-mil-spec { background: rgba(75,105,255,0.12); } +.bg-rarity-restricted { background: rgba(136,71,255,0.12); } +.bg-rarity-classified { background: rgba(211,44,230,0.12); } +.bg-rarity-covert { background: rgba(235,75,75,0.12); } +.bg-rarity-rare-special { background: rgba(255,215,0,0.12); } +.glow-rarity-covert { box-shadow: 0 0 20px rgba(235,75,75,0.2); } +.glow-rarity-rare-special { box-shadow: 0 0 20px rgba(255,215,0,0.25); } + +/* ── Admin Layout ── */ +.admin-body { display: flex; min-height: 100vh; } +.admin-sidebar { + width: 240px; background: var(--bg-dark); border-right: 1px solid var(--border); + display: flex; flex-direction: column; flex-shrink: 0; + position: sticky; top: 0; height: 100vh; overflow-y: auto; +} +.admin-sidebar-brand { + padding: 1rem 1.15rem; border-bottom: 1px solid var(--border); + font-family: var(--font-display); font-size: 1rem; + display: flex; align-items: center; gap: 0.4rem; +} +.admin-sidebar-brand span { color: var(--primary); } +.admin-sidebar-nav { padding: 0.5rem; flex: 1; } +.admin-sidebar-link { + display: flex; align-items: center; gap: 0.5rem; + padding: 0.5rem 0.75rem; color: var(--text-dim); text-decoration: none; + border-radius: var(--radius-sm); transition: all var(--transition); + font-size: 0.85rem; +} +.admin-sidebar-link:hover { color: var(--text); background: var(--bg-hover); } +.admin-sidebar-link.active { color: var(--primary); background: var(--primary-subtle); } +.admin-sidebar-footer { padding: 0.75rem; border-top: 1px solid var(--border); } +.admin-main { flex: 1; min-width: 0; display: flex; flex-direction: column; } +.admin-topbar { + display: flex; align-items: center; justify-content: space-between; + padding: 0.75rem 1.5rem; border-bottom: 1px solid var(--border); + background: var(--bg-dark); flex-wrap: wrap; gap: 0.5rem; +} +.admin-topbar-title { font-family: var(--font-display); font-size: 1.1rem; } +.admin-topbar-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; } +.admin-content { padding: 1.5rem; flex: 1; } +.a-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 1.15rem; } +.a-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.75rem; margin-bottom: 1.25rem; } +.a-stat { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 0.9rem 1rem; } +.a-stat-value { font-family: var(--font-display); font-size: 1.3rem; color: var(--primary); } +.a-stat-label { font-size: 0.72rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.04em; margin-top: 0.1rem; } +.a-table { width: 100%; } +.a-btn { padding: 0.4rem 0.85rem; border: none; border-radius: var(--radius-sm); font-size: 0.75rem; font-weight: 600; cursor: pointer; text-transform: uppercase; letter-spacing: 0.04em; transition: all var(--transition); font-family: var(--font-body); } +.a-btn-primary { background: var(--primary); color: #000; } +.a-btn-primary:hover { box-shadow: 0 4px 12px var(--primary-glow); } +.a-btn-danger { background: var(--danger); color: #fff; } +.a-btn-success { background: var(--success); color: #000; } +.a-btn-outline { background: transparent; border: 1px solid var(--border-light); color: var(--text-dim); } +.a-btn-outline:hover { color: var(--text); border-color: rgba(255,255,255,0.2); } +.a-input { + width: 100%; padding: 0.4rem 0.7rem; font-size: 0.85rem; + background: var(--bg-dark); border: 1px solid var(--border-light); + border-radius: var(--radius-sm); color: var(--text); outline: none; + font-family: var(--font-body); transition: border-color var(--transition); +} +.a-input:focus { border-color: var(--primary); } +.a-badge { display: inline-flex; padding: 0.1rem 0.45rem; border-radius: 4px; font-size: 0.65rem; font-weight: 600; text-transform: uppercase; } +.a-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.7); z-index: var(--z-overlay); display: flex; align-items: center; justify-content: center; padding: 1rem; animation: fadeIn 0.15s ease; } +.a-modal { background: var(--bg-surface); border: 1px solid var(--border-light); border-radius: var(--radius-lg); width: 100%; max-width: 520px; max-height: 85vh; overflow-y: auto; animation: modalSlideIn 0.2s ease; box-shadow: var(--shadow-xl); } +.a-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 0.85rem 1.15rem; border-bottom: 1px solid var(--border); } +.a-modal-title { font-family: var(--font-display); font-size: 0.95rem; } +.a-modal-close { background: none; border: none; color: var(--text-dim); font-size: 1.2rem; cursor: pointer; padding: 0.1rem; line-height: 1; transition: color var(--transition); } +.a-modal-close:hover { color: var(--text); } +.a-modal-body { padding: 1.15rem; } +.a-modal-footer { display: flex; justify-content: flex-end; gap: 0.5rem; padding: 0.85rem 1.15rem; border-top: 1px solid var(--border); } +@media (max-width: 768px) { + .admin-sidebar { width: 60px; } + .admin-sidebar-brand span, .admin-sidebar-link span { display: none; } + .admin-sidebar-link { justify-content: center; padding: 0.6rem; } + .admin-sidebar-footer { display: none; } } -/* Улучшенные ссылки */ -a:not(.btn):not(.nav-link):not(.logo) { - color: var(--primary-color); - text-decoration: none; - border-bottom: 1px solid transparent; - transition: border-color 0.2s; +/* ── Utilities ── */ +.flex { display: flex; } +.flex-col { flex-direction: column; } +.items-center { align-items: center; } +.justify-between { justify-content: space-between; } +.justify-center { justify-content: center; } +.gap-1 { gap: 0.25rem; } +.gap-2 { gap: 0.5rem; } +.gap-3 { gap: 0.75rem; } +.gap-4 { gap: 1rem; } +.mt-1 { margin-top: 0.25rem; } +.mt-2 { margin-top: 0.5rem; } +.mt-3 { margin-top: 0.75rem; } +.mt-4 { margin-top: 1rem; } +.mb-2 { margin-bottom: 0.5rem; } +.mb-4 { margin-bottom: 1rem; } +.text-center { text-align: center; } +.text-dim { color: var(--text-dim); } +.text-primary { color: var(--primary); } +.text-sm { font-size: 0.78rem; } +.text-xs { font-size: 0.7rem; } +.font-display { font-family: var(--font-display); } +.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.w-full { width: 100%; } + +/* ── Animations ── */ +@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } } +@keyframes pulseGlow { 0%,100% { box-shadow: 0 0 8px var(--primary-glow); } 50% { box-shadow: 0 0 25px rgba(245,158,11,0.5); } } +@keyframes slideInUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } +@keyframes slideInDown { from { transform: translateY(-20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } +@keyframes scaleIn { from { transform: scale(0.9); opacity: 0; } to { transform: scale(1); opacity: 1; } } +@keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } +@keyframes float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-6px); } } +@keyframes shake { 0%,100% { transform: translateX(0); } 20% { transform: translateX(-4px); } 40% { transform: translateX(4px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(3px); } } +.animate-pulse { animation: pulse 2s ease-in-out infinite; } +.animate-float { animation: float 3s ease-in-out infinite; } +.animate-shake { animation: shake 0.4s ease; } +.animate-slideUp { animation: slideInUp 0.3s ease; } +.animate-scaleIn { animation: scaleIn 0.25s ease; } + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } +} + +/* ── Responsive helpers ── */ +@media (max-width: 1024px) { + .container { padding: 0 15px; } +} +@media (max-width: 768px) { + .hero { padding: 2.5rem 0; } + .section { padding: 1.5rem 0; } + .stats-grid { grid-template-columns: repeat(2, 1fr); } + .admin-content { padding: 1rem; } + .admin-topbar { padding: 0.6rem 1rem; } +} +@media (max-width: 480px) { + .stats-grid { grid-template-columns: 1fr; } + .hero-actions { flex-direction: column; align-items: stretch; } + .hero-actions .btn { justify-content: center; } } -a:not(.btn):not(.nav-link):not(.logo):hover { - border-bottom-color: var(--primary-color); -} \ No newline at end of file diff --git a/static/js/app.js b/static/js/app.js index e2bc26c..0a8c690 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -1,155 +1,132 @@ -// ─── Shared CS2 Simulator Utilities ───────────────────────────────────────── - -// Logout async function logout() { - try { - await fetch('/web/api/auth/logout', { method: 'POST' }); - } catch (e) {} - window.location.href = '/'; + try { await fetch('/web/api/auth/logout', { method: 'POST' }); } catch (e) {} + window.location.href = '/'; } -// Refresh balance display async function refreshBalance() { - try { - const res = await fetch('/web/api/user/balance'); - const data = await res.json(); - if (data.success) { - document.querySelectorAll('.user-balance').forEach(el => { - el.textContent = `${Math.floor(data.balance)} ₽`; - }); - } - } catch (e) {} -} - -// Rarity colors -function getRarityColor(rarity) { - const colors = { - 'Consumer Grade': '#b0b0b0', - 'Industrial Grade': '#5e98d9', - 'Mil-Spec': '#4b69ff', - 'Mil-Spec Grade': '#4b69ff', - 'Restricted': '#8847ff', - 'Classified': '#d32ce6', - 'Covert': '#eb4b4b', - 'Rare Special Item': '#ffd700', - 'Extraordinary': '#ffd700', - }; - return colors[rarity] || '#b0b0b0'; -} - -// Format number with spaces -function formatNumber(n) { - return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' '); -} - -// Debounce -function debounce(fn, ms = 300) { - let timer; - return function (...args) { - clearTimeout(timer); - timer = setTimeout(() => fn.apply(this, args), ms); - }; -} - -// Escape HTML -function escapeHtml(str) { - const div = document.createElement('div'); - div.textContent = str; - return div.innerHTML; -} - -// Show notification -function showNotification(message, type = 'info', duration = 3000) { - const existing = document.querySelector('.notification-toast'); - if (existing) existing.remove(); - - const colors = { - success: '#22c55e', - error: '#ef4444', - info: '#3b82f6', - warning: '#f59e0b', - }; - - const toast = document.createElement('div'); - toast.className = 'notification-toast'; - toast.style.cssText = ` - position: fixed; top: 20px; right: 20px; z-index: 99999; - background: #1a1a2e; border: 1px solid ${colors[type] || colors.info}; - color: white; padding: 12px 20px; border-radius: 8px; - font-size: 14px; box-shadow: 0 10px 40px rgba(0,0,0,0.5); - animation: slideInRight 0.3s ease; max-width: 400px; - `; - toast.textContent = message; - document.body.appendChild(toast); - - setTimeout(() => { - toast.style.animation = 'slideOutRight 0.3s ease forwards'; - setTimeout(() => toast.remove(), 300); - }, duration); -} - -// Inject notification styles once -if (!document.getElementById('notificationStyles')) { - const style = document.createElement('style'); - style.id = 'notificationStyles'; - style.textContent = ` - @keyframes slideInRight { - from { transform: translateX(120%); opacity: 0; } - to { transform: translateX(0); opacity: 1; } - } - @keyframes slideOutRight { - from { transform: translateX(0); opacity: 1; } - to { transform: translateX(120%); opacity: 0; } - } - `; - document.head.appendChild(style); -} - -// Show achievement popup (global function used by templates) -function showAchievementPopup(title, reward) { - let popup = document.getElementById('achievementGlobalPopup'); - if (!popup) { - popup = document.createElement('div'); - popup.id = 'achievementGlobalPopup'; - popup.style.cssText = ` - position: fixed; top: 20px; left: 50%; transform: translateX(-50%); - z-index: 99999; background: linear-gradient(135deg, #1a3a1a, #0d260d); - border: 1px solid #22c55e; border-radius: 12px; padding: 1rem 1.5rem; - box-shadow: 0 10px 40px rgba(0,0,0,0.5); - animation: slideInDown 0.5s ease; max-width: 400px; width: 90%; - text-align: center; - `; - popup.innerHTML = ` -
🏆 Новое достижение!
-
-
- `; - document.body.appendChild(popup); - - if (!document.getElementById('slideInDownStyle')) { - const s = document.createElement('style'); - s.id = 'slideInDownStyle'; - s.textContent = ` - @keyframes slideInDown { - from { transform: translateX(-50%) translateY(-120%); opacity: 0; } - to { transform: translateX(-50%) translateY(0); opacity: 1; } - } - `; - document.head.appendChild(s); + try { + const res = await fetch('/web/api/user/balance'); + const data = await res.json(); + if (data.success) { + document.querySelectorAll('.user-balance').forEach(el => { + const old = el.textContent; + const val = `${Math.floor(data.balance)} ₽`; + if (old !== val) { + el.textContent = val; + el.classList.remove('animate-scaleIn'); + void el.offsetWidth; + el.classList.add('animate-scaleIn'); } + }); } - - document.getElementById('globalPopupTitle').textContent = title; - document.getElementById('globalPopupReward').textContent = reward ? `+${reward} ₽` : ''; - popup.style.display = 'block'; - - if (window.SoundManager) SoundManager.achievement(); - - setTimeout(() => { - popup.style.animation = 'slideInDown 0.5s ease reverse forwards'; - setTimeout(() => { - popup.style.display = 'none'; - popup.style.animation = 'slideInDown 0.5s ease'; - }, 500); - }, 4000); + } catch (e) {} } + +function getRarityColor(rarity) { + const colors = { + 'Consumer Grade': '#b0b0b0', + 'Industrial Grade': '#5e98d9', + 'Mil-Spec': '#4b69ff', + 'Mil-Spec Grade': '#4b69ff', + 'Restricted': '#8847ff', + 'Classified': '#d32ce6', + 'Covert': '#eb4b4b', + 'Rare Special Item': '#ffd700', + 'Extraordinary': '#ffd700', + }; + return colors[rarity] || '#b0b0b0'; +} + +function formatNumber(n) { + return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' '); +} + +function debounce(fn, ms = 300) { + let timer; + return function (...args) { + clearTimeout(timer); + timer = setTimeout(() => fn.apply(this, args), ms); + }; +} + +function escapeHtml(str) { + const div = document.createElement('div'); + div.textContent = str; + return div.innerHTML; +} + +function showNotification(message, type = 'info', duration = 3000) { + let container = document.getElementById('toastContainer'); + if (!container) { + container = document.createElement('div'); + container.id = 'toastContainer'; + container.className = 'toast-container'; + document.body.appendChild(container); + } + + const icons = { success: '✓', error: '✗', info: 'ℹ', warning: '⚠' }; + const toast = document.createElement('div'); + toast.className = `toast toast-${type} animate-slideUp`; + toast.innerHTML = `${icons[type] || ''}${message}`; + container.appendChild(toast); + + setTimeout(() => { + toast.style.opacity = '0'; + toast.style.transform = 'translateX(100%)'; + toast.style.transition = 'all 0.3s ease'; + setTimeout(() => toast.remove(), 300); + }, duration); +} + +function showAchievementPopup(title, reward) { + let popup = document.getElementById('achievementGlobalPopup'); + if (!popup) { + popup = document.createElement('div'); + popup.id = 'achievementGlobalPopup'; + popup.className = 'modal-overlay'; + popup.style.background = 'rgba(0,0,0,0.5)'; + popup.style.alignItems = 'flex-start'; + popup.style.paddingTop = '60px'; + popup.innerHTML = ` +
+
🏆 Достижение разблокировано!
+
+
+
+ `; + document.body.appendChild(popup); + } + + document.getElementById('globalPopupTitle').textContent = title; + document.getElementById('globalPopupReward').textContent = reward ? `+${reward} ₽` : ''; + popup.style.display = 'flex'; + + if (window.SoundManager) SoundManager.achievement(); + + setTimeout(() => { + popup.style.display = 'none'; + }, 4000); +} + +document.addEventListener('DOMContentLoaded', () => { + const toggle = document.getElementById('mobileToggle'); + const nav = document.getElementById('navLinks'); + if (toggle && nav) { + toggle.addEventListener('click', () => { + nav.classList.toggle('open'); + }); + document.addEventListener('click', (e) => { + if (!toggle.contains(e.target) && !nav.contains(e.target)) { + nav.classList.remove('open'); + } + }); + } + + const soundToggle = document.getElementById('soundToggle'); + if (soundToggle && window.SoundManager) { + soundToggle.addEventListener('click', () => { + const enabled = SoundManager.toggle(); + soundToggle.textContent = enabled ? '🔊' : '🔇'; + }); + } +}); diff --git a/static/js/sounds.js b/static/js/sounds.js index 3035950..921d528 100644 --- a/static/js/sounds.js +++ b/static/js/sounds.js @@ -1,185 +1,349 @@ -// Sound effects system using Web Audio API - no external files needed const SoundManager = { - _ctx: null, - _enabled: true, - _volume: 0.3, + _ctx: null, + _master: null, + _analyser: null, + _enabled: true, + _volume: 0.3, + _ambient: null, + _ambientGain: null, + _initCalled: false, - init() { - try { - this._ctx = new (window.AudioContext || window.webkitAudioContext)(); - } catch (e) { - console.warn('Web Audio API not supported'); - this._enabled = false; - } - const saved = localStorage.getItem('sound_enabled'); - if (saved !== null) this._enabled = saved === 'true'; - }, - - setEnabled(on) { - this._enabled = on; - localStorage.setItem('sound_enabled', on); - }, - - toggle() { - this.setEnabled(!this._enabled); - return this._enabled; - }, - - _play(freq, duration, type = 'sine', volume = 1) { - if (!this._enabled || !this._ctx) return; - if (this._ctx.state === 'suspended') this._ctx.resume(); - - const osc = this._ctx.createOscillator(); - const gain = this._ctx.createGain(); - osc.type = type; - osc.frequency.setValueAtTime(freq, this._ctx.currentTime); - gain.gain.setValueAtTime(this._volume * volume, this._ctx.currentTime); - gain.gain.exponentialRampToValueAtTime(0.001, this._ctx.currentTime + duration); - osc.connect(gain); - gain.connect(this._ctx.destination); - osc.start(); - osc.stop(this._ctx.currentTime + duration); - }, - - _noise(duration, volume = 1) { - if (!this._enabled || !this._ctx) return; - if (this._ctx.state === 'suspended') this._ctx.resume(); - - const bufferSize = this._ctx.sampleRate * duration; - const buffer = this._ctx.createBuffer(1, bufferSize, this._ctx.sampleRate); - const data = buffer.getChannelData(0); - for (let i = 0; i < bufferSize; i++) { - data[i] = Math.random() * 2 - 1; - } - const source = this._ctx.createBufferSource(); - source.buffer = buffer; - const gain = this._ctx.createGain(); - gain.gain.setValueAtTime(this._volume * volume, this._ctx.currentTime); - gain.gain.exponentialRampToValueAtTime(0.001, this._ctx.currentTime + duration); - source.connect(gain); - gain.connect(this._ctx.destination); - source.start(); - }, - - caseOpen() { - // Descending sweep with click - this._play(800, 0.1, 'square', 0.3); - setTimeout(() => this._play(400, 0.15, 'sawtooth', 0.2), 80); - setTimeout(() => this._play(200, 0.2, 'sine', 0.15), 180); - this._noise(0.05, 0.4); - }, - - caseRare() { - // Ascending bright chime for rare items - this._play(523, 0.15, 'sine', 0.3); - setTimeout(() => this._play(659, 0.15, 'sine', 0.3), 100); - setTimeout(() => this._play(784, 0.15, 'sine', 0.3), 200); - setTimeout(() => this._play(1047, 0.3, 'sine', 0.4), 300); - }, - - caseCovert() { - // Epic sound for covert/knife - this._play(392, 0.2, 'sawtooth', 0.3); - setTimeout(() => this._play(523, 0.2, 'sawtooth', 0.3), 150); - setTimeout(() => this._play(659, 0.2, 'sawtooth', 0.3), 300); - setTimeout(() => this._play(784, 0.4, 'sine', 0.5), 450); - setTimeout(() => this._play(1047, 0.6, 'sine', 0.6), 600); - }, - - slotSpin() { - // Ratcheting sound for slot reels - for (let i = 0; i < 8; i++) { - setTimeout(() => { - this._play(300 + Math.random() * 400, 0.05, 'square', 0.15); - }, i * 80); - } - }, - - slotMatch() { - // Win jingle - this._play(523, 0.1, 'sine', 0.3); - setTimeout(() => this._play(659, 0.1, 'sine', 0.3), 100); - setTimeout(() => this._play(784, 0.1, 'sine', 0.3), 200); - setTimeout(() => this._play(1047, 0.4, 'sine', 0.5), 300); - }, - - contractSubmit() { - // Mechanical sound - this._play(150, 0.3, 'sawtooth', 0.2); - setTimeout(() => this._play(200, 0.2, 'square', 0.2), 200); - setTimeout(() => this._play(250, 0.1, 'square', 0.15), 350); - }, - - contractResult() { - // Rising success - this._play(400, 0.15, 'sine', 0.3); - setTimeout(() => this._play(600, 0.15, 'sine', 0.3), 120); - setTimeout(() => this._play(800, 0.3, 'sine', 0.4), 240); - }, - - wheelSpin() { - // Ticking as wheel rotates - this._play(200, 0.03, 'square', 0.1); - }, - - wheelWin() { - // Celebration - this._play(523, 0.15, 'sine', 0.3); - setTimeout(() => this._play(659, 0.15, 'sine', 0.3), 120); - setTimeout(() => this._play(784, 0.2, 'sine', 0.35), 240); - setTimeout(() => this._play(1047, 0.5, 'sine', 0.5), 360); - }, - - wheelLose() { - // Sad trombone - this._play(400, 0.2, 'sine', 0.2); - setTimeout(() => this._play(350, 0.2, 'sine', 0.2), 150); - setTimeout(() => this._play(300, 0.3, 'sine', 0.15), 300); - }, - - achievement() { - // Achievement unlock - this._play(659, 0.1, 'sine', 0.3); - setTimeout(() => this._play(523, 0.1, 'sine', 0.3), 100); - setTimeout(() => this._play(784, 0.1, 'sine', 0.3), 200); - setTimeout(() => this._play(659, 0.1, 'sine', 0.3), 300); - setTimeout(() => this._play(1047, 0.4, 'sine', 0.5), 400); - }, - - crashBet() { - this._play(300, 0.1, 'square', 0.15); - }, - - crashTick() { - this._play(500 + Math.random() * 500, 0.03, 'sine', 0.08); - }, - - crashCrashed() { - // Explosion - this._noise(0.3, 0.6); - this._play(80, 0.5, 'sawtooth', 0.4); - setTimeout(() => this._play(50, 0.8, 'sine', 0.3), 100); - }, - - crashCashout() { - // Cashout success - this._play(600, 0.1, 'sine', 0.3); - setTimeout(() => this._play(800, 0.1, 'sine', 0.3), 80); - setTimeout(() => this._play(1000, 0.2, 'sine', 0.4), 160); - }, - - click() { - this._play(800, 0.03, 'sine', 0.1); - }, - - error() { - this._play(200, 0.15, 'square', 0.2); - }, - - balanceUpdate() { - this._play(1000, 0.05, 'sine', 0.1); + init() { + if (this._initCalled) return; + this._initCalled = true; + try { + this._ctx = new (window.AudioContext || window.webkitAudioContext)(); + this._master = this._ctx.createGain(); + this._master.gain.value = this._volume; + this._master.connect(this._ctx.destination); + } catch (e) { + console.warn('Web Audio API not supported'); + this._enabled = false; } + const saved = localStorage.getItem('sound_enabled'); + if (saved !== null) this._enabled = saved === 'true'; + const vol = localStorage.getItem('sound_volume'); + if (vol !== null) this.setVolume(parseFloat(vol)); + + document.addEventListener('click', () => { + if (this._ctx && this._ctx.state === 'suspended') this._ctx.resume(); + }, { once: true }); + }, + + setEnabled(on) { + this._enabled = on; + localStorage.setItem('sound_enabled', on); + if (!on && this._ambientGain) { + this._ambientGain.gain.setTargetAtTime(0, this._ctx.currentTime, 0.5); + } + }, + + toggle() { + this.setEnabled(!this._enabled); + return this._enabled; + }, + + setVolume(v) { + this._volume = Math.max(0, Math.min(1, v)); + if (this._master) this._master.gain.value = this._volume; + localStorage.setItem('sound_volume', this._volume); + }, + + _t() { + return this._ctx ? this._ctx.currentTime : 0; + }, + + _osc(freq, duration, type = 'sine', vol = 1, dest) { + if (!this._enabled || !this._ctx) return; + if (this._ctx.state === 'suspended') this._ctx.resume(); + const now = this._t(); + const o = this._ctx.createOscillator(); + const g = this._ctx.createGain(); + o.type = type; + o.frequency.setValueAtTime(freq, now); + g.gain.setValueAtTime(vol, now); + g.gain.exponentialRampToValueAtTime(0.001, now + duration); + o.connect(g); + g.connect(dest || this._master); + o.start(now); + o.stop(now + duration); + }, + + _noise(duration, vol = 1, filterFreq, dest) { + if (!this._enabled || !this._ctx) return; + if (this._ctx.state === 'suspended') this._ctx.resume(); + const now = this._t(); + const sr = this._ctx.sampleRate; + const len = sr * duration; + const buf = this._ctx.createBuffer(1, len, sr); + const data = buf.getChannelData(0); + for (let i = 0; i < len; i++) data[i] = Math.random() * 2 - 1; + const src = this._ctx.createBufferSource(); + src.buffer = buf; + let node = src; + if (filterFreq) { + const f = this._ctx.createBiquadFilter(); + f.type = 'lowpass'; + f.frequency.value = filterFreq; + src.connect(f); + node = f; + } + const g = this._ctx.createGain(); + g.gain.setValueAtTime(vol, now); + g.gain.exponentialRampToValueAtTime(0.001, now + duration); + node.connect(g); + g.connect(dest || this._master); + src.start(now); + }, + + _chord(freqs, duration, type = 'sine', vol = 0.15) { + freqs.forEach(f => this._osc(f, duration, type, vol / freqs.length)); + }, + + // ── Rarity color helpers ── + _rarityParams(rarity) { + const map = { + 'Consumer Grade': { baseFreq: 300, arp: [300, 350, 400], noiseVol: 0.2, dur: 0.6 }, + 'Industrial Grade': { baseFreq: 400, arp: [400, 500, 600], noiseVol: 0.2, dur: 0.7 }, + 'Mil-Spec': { baseFreq: 500, arp: [500, 630, 750], noiseVol: 0.25, dur: 0.8 }, + 'Mil-Spec Grade': { baseFreq: 500, arp: [500, 630, 750], noiseVol: 0.25, dur: 0.8 }, + 'Restricted': { baseFreq: 600, arp: [600, 750, 900], noiseVol: 0.3, dur: 1.0 }, + 'Classified': { baseFreq: 700, arp: [700, 880, 1050], noiseVol: 0.35, dur: 1.2 }, + 'Covert': { baseFreq: 800, arp: [800, 1000, 1200], noiseVol: 0.4, dur: 1.5 }, + 'Rare Special Item': { baseFreq: 900, arp: [900, 1100, 1400], noiseVol: 0.45, dur: 1.8 }, + 'Extraordinary': { baseFreq: 900, arp: [900, 1100, 1400], noiseVol: 0.45, dur: 1.8 }, + }; + return map[rarity] || map['Consumer Grade']; + }, + + // ── Ambient ── + startAmbient() { + if (!this._ctx || this._ambient) return; + const now = this._t(); + this._ambientGain = this._ctx.createGain(); + this._ambientGain.gain.value = 0; + + const bufLen = this._ctx.sampleRate * 2; + const buf = this._ctx.createBuffer(1, bufLen, this._ctx.sampleRate); + const data = buf.getChannelData(0); + for (let i = 0; i < bufLen; i++) { + const t = i / this._ctx.sampleRate; + data[i] = (Math.random() - 0.5) * 0.5 + + Math.sin(2 * Math.PI * 55 * t) * 0.08 + + Math.sin(2 * Math.PI * 82.5 * t) * 0.05; + } + const src = this._ctx.createBufferSource(); + src.buffer = buf; + src.loop = true; + + const lp = this._ctx.createBiquadFilter(); + lp.type = 'lowpass'; + lp.frequency.value = 300; + + const hp = this._ctx.createBiquadFilter(); + hp.type = 'highpass'; + hp.frequency.value = 40; + + src.connect(lp); + lp.connect(hp); + hp.connect(this._ambientGain); + this._ambientGain.connect(this._master); + src.start(); + this._ambient = src; + this._ambientGain.gain.setTargetAtTime(0.06, now, 1); + }, + + stopAmbient() { + if (this._ambientGain) { + this._ambientGain.gain.setTargetAtTime(0, this._t(), 0.5); + setTimeout(() => { + if (this._ambient) { try { this._ambient.stop(); } catch (e) {} this._ambient = null; } + }, 1500); + } + }, + + // ── Case Opening ── + caseOpen() { + this._noise(0.15, 0.4, 2000); + this._osc(700, 0.06, 'square', 0.25); + setTimeout(() => this._osc(500, 0.08, 'square', 0.2), 50); + setTimeout(() => this._osc(350, 0.1, 'sawtooth', 0.18), 110); + setTimeout(() => this._osc(250, 0.12, 'sine', 0.12), 180); + setTimeout(() => this._noise(0.3, 0.15, 4000), 120); + }, + + caseReveal(rarity) { + const p = this._rarityParams(rarity); + this._noise(0.08, 0.3, 3000); + p.arp.forEach((f, i) => { + setTimeout(() => { + this._osc(f, 0.15, 'sine', 0.25); + this._osc(f * 2, 0.1, 'sine', 0.08); + }, i * 100); + }); + setTimeout(() => { + this._osc(p.baseFreq * 2, 0.4, 'sine', 0.35); + this._noise(0.15, p.noiseVol, 5000); + this._osc(p.baseFreq, 0.6, 'sawtooth', 0.15); + }, p.arp.length * 100); + }, + + caseCovert() { + this._noise(0.1, 0.5, 4000); + [392, 523, 659, 784, 1047].forEach((f, i) => { + setTimeout(() => { + this._osc(f, 0.2, 'sawtooth', 0.3); + this._osc(f * 1.5, 0.15, 'sine', 0.1); + }, i * 120); + }); + setTimeout(() => { + this._osc(1047, 0.8, 'sine', 0.6); + this._osc(784, 0.6, 'triangle', 0.25); + this._noise(0.6, 0.4, 6000); + }, 600); + }, + + caseRare() { + [523, 659, 784, 1047].forEach((f, i) => { + setTimeout(() => { + this._osc(f, 0.12, 'sine', 0.3); + this._osc(f * 1.5, 0.08, 'sine', 0.06); + }, i * 80); + }); + setTimeout(() => this._osc(1319, 0.5, 'sine', 0.5), 320); + }, + + // ── Slots ── + slotSpin() { + for (let i = 0; i < 10; i++) { + setTimeout(() => { + this._osc(200 + Math.random() * 600, 0.04, 'square', 0.12); + }, i * 60); + } + }, + + slotMatch() { + [523, 659, 784, 1047].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.15, 'sine', 0.35), i * 100); + }); + setTimeout(() => this._noise(0.2, 0.3, 8000), 300); + }, + + // ── Contract ── + contractSubmit() { + this._osc(150, 0.25, 'sawtooth', 0.2); + setTimeout(() => this._osc(200, 0.15, 'square', 0.18), 150); + setTimeout(() => { + this._osc(250, 0.08, 'square', 0.15); + this._noise(0.05, 0.15); + }, 280); + }, + + contractResult() { + [400, 600, 800].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.15, 'sine', 0.3), i * 100); + }); + setTimeout(() => { + this._osc(1200, 0.4, 'sine', 0.45); + this._noise(0.2, 0.2, 5000); + }, 300); + }, + + // ── Wheel ── + wheelTick() { + this._osc(200, 0.03, 'square', 0.08); + }, + + wheelWin() { + [523, 659, 784, 1047].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.18, 'sine', 0.35), i * 100); + }); + setTimeout(() => this._noise(0.4, 0.3, 8000), 400); + }, + + wheelLose() { + [400, 350, 300].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.25, 'sine', 0.2), i * 150); + }); + }, + + // ── Achievements ── + achievement() { + [659, 523, 784, 659, 1047].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.12, 'sine', 0.3), i * 80); + }); + setTimeout(() => this._noise(0.3, 0.25, 6000), 400); + }, + + // ── Crash ── + crashBet() { + this._osc(300, 0.08, 'square', 0.15); + setTimeout(() => this._osc(350, 0.06, 'square', 0.1), 60); + }, + + crashTick(multiplier) { + const freq = 300 + Math.min(multiplier * 50, 800); + this._osc(freq, 0.03, 'sine', 0.05 + Math.min(multiplier * 0.01, 0.15)); + }, + + crashCrashed() { + this._noise(0.5, 0.6, 2000); + this._osc(80, 0.6, 'sawtooth', 0.4); + setTimeout(() => this._osc(50, 1, 'sine', 0.3), 100); + setTimeout(() => this._osc(40, 0.8, 'triangle', 0.2), 200); + }, + + crashCashout(multiplier) { + const vol = 0.2 + Math.min(multiplier * 0.02, 0.5); + [600, 800, 1000, 1200].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.12, 'sine', vol), i * 80); + }); + setTimeout(() => this._noise(0.3, 0.3, 8000), 320); + }, + + // ── Upgrade ── + upgradeSubmit() { + this._osc(250, 0.1, 'square', 0.15); + this._noise(0.05, 0.2); + }, + + upgradeResult() { + [523, 784, 1047].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.2, 'sine', 0.3), i * 120); + }); + setTimeout(() => this._noise(0.25, 0.25, 6000), 360); + }, + + upgradeFail() { + [300, 250, 200].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.2, 'sawtooth', 0.2), i * 120); + }); + }, + + // ── UI ── + click() { + this._osc(800, 0.03, 'sine', 0.08); + }, + + hover() { + this._osc(1200, 0.015, 'sine', 0.03); + }, + + error() { + this._osc(200, 0.15, 'square', 0.2); + setTimeout(() => this._osc(180, 0.12, 'square', 0.15), 100); + }, + + success() { + [600, 800, 1000].forEach((f, i) => { + setTimeout(() => this._osc(f, 0.08, 'sine', 0.2), i * 60); + }); + }, + + balanceUpdate() { + this._osc(1000, 0.04, 'sine', 0.08); + setTimeout(() => this._osc(1200, 0.04, 'sine', 0.06), 50); + }, }; -// Auto-init document.addEventListener('DOMContentLoaded', () => SoundManager.init()); diff --git a/templates/_activity_sidebar.html b/templates/_activity_sidebar.html index 484c579..a760827 100644 --- a/templates/_activity_sidebar.html +++ b/templates/_activity_sidebar.html @@ -1,203 +1,86 @@
-

Лента

- + + + Лента + + 0 👤 - +
-
Загрузка...
+
Загрузка...
- + diff --git a/templates/achievements.html b/templates/achievements.html index ba1e16a..67fb198 100644 --- a/templates/achievements.html +++ b/templates/achievements.html @@ -3,320 +3,107 @@ - Достижения - CS2 Simulator + Достижения — CS2 Simulator - -
-
-
-

🏆 Достижения

-

Выполняй задания и получай награды

-
-
-
-
{{ unlocked }}
-
Открыто
+
+
+
+
+

🏆 Достижения

+

Выполняй задания и получай награды

-
-
{{ total }}
-
Всего
-
-
-
{{ "%.0f"|format(unlocked/total*100 if total > 0 else 0) }}%
-
Прогресс
-
-
-
- -
- - - - - - -
- -
- {% for ach in achievements %} -
-
{{ ach.icon }}
-
-
{{ ach.title }}
-
{{ ach.description }}
- {% if ach.reward_amount > 0 %} -
+{{ "%.0f"|format(ach.reward_amount) }} ₽
- {% endif %} -
-
-
-
-
- {% if ach.unlocked %} - ✅ Получено - {% else %} - {{ ach.progress }} / {{ ach.requirement_value }} - {% endif %} -
+
+
+
{{ unlocked }}/{{ total }}
+
Открыто
+
+
+
{{ "%.0f"|format(unlocked/total*100 if total > 0 else 0) }}%
+
Прогресс
- {% endfor %} + +
+ + + + + + +
+ +
+ {% for ach in achievements %} +
+
+ {{ ach.icon }} +
+
+
{{ ach.title }}
+
{{ ach.description }}
+ {% if ach.reward_amount > 0 %} +
+{{ "%.0f"|format(ach.reward_amount) }} ₽
+ {% endif %} +
+
+
+
+
+ {% if ach.unlocked %}✅ Получено{% else %}{{ ach.progress }} / {{ ach.requirement_value }}{% endif %} +
+
+
+
+ {% endfor %} +
- - - {% include '_activity_sidebar.html' %} diff --git a/templates/activity.html b/templates/activity.html index ae15909..4b66039 100644 --- a/templates/activity.html +++ b/templates/activity.html @@ -3,123 +3,33 @@ - Лента активностей - CS2 Simulator + Лента активностей — CS2 Simulator - -
-
-
-

📰 Лента активностей

-

Что происходит на сервере

-
-
- - Live -
-
- -
- {% if activities %} - {% for a in activities %} -
-
- {% if a.activity_type == 'case_open' %}📦 - {% elif a.activity_type == 'contract' %}🔄 - {% elif a.activity_type == 'upgrade' %}🆙 - {% elif a.activity_type == 'achievement' %}🏆 - {% elif a.activity_type == 'crash' %}💥 - {% else %}📌{% endif %} +
+
+
+
+

📰 Лента активностей

+

Что происходит на сервере

-
-
{{ a.message }}
-
- {{ a.username }} - • {{ a.created_at }} +
+ + Live +
+
+ +
+ {% if activities %} + {% for a in activities %} +
+
+ {% if a.activity_type == 'case_open' %}📦 + {% elif a.activity_type == 'contract' %}🔄 + {% elif a.activity_type == 'upgrade' %}🆙 + {% elif a.activity_type == 'achievement' %}🏆 + {% elif a.activity_type == 'crash' %}💥 + {% else %}📌{% endif %} +
+
+
{{ a.message }}
+
+ {{ a.username }} + • {{ a.created_at }} +
+ {% endfor %} + {% else %} +
+
📭
+

Пока нет активностей

+

Открой кейс или выполни контракт — это появится здесь в реальном времени!

+
+ {% endif %}
- {% endfor %} - {% else %} -
-
📭
-

Пока нет активностей

-

Открой кейс или выполни контракт — это появится здесь в реальном времени!

-
- {% endif %}
@@ -175,71 +87,37 @@ - +{% include '_activity_sidebar.html' %} diff --git a/templates/admin/base.html b/templates/admin/base.html index 56e09fc..8f34359 100644 --- a/templates/admin/base.html +++ b/templates/admin/base.html @@ -6,353 +6,93 @@ {% block title %}Админ-панель{% endblock %} — CS2 Simulator - +
-
- {% block page_title %}Панель управления{% endblock %} -
-
- {% block top_actions %}{% endblock %} -
-
-
- {% block content %}{% endblock %} +
{% block page_title %}Панель управления{% endblock %}
+
{% block top_actions %}{% endblock %}
+
{% block content %}{% endblock %}
{% block modals %}{% endblock %} diff --git a/templates/admin/cases.html b/templates/admin/cases.html index 334aff7..d6871ee 100644 --- a/templates/admin/cases.html +++ b/templates/admin/cases.html @@ -2,9 +2,7 @@ {% block title %}Кейсы — Админ-панель{% endblock %} {% block nav_cases %}active{% endblock %} {% block page_title %}📦 Управление кейсами{% endblock %} -{% block top_actions %} - -{% endblock %} +{% block top_actions %}{% endblock %} {% block content %}
@@ -64,29 +62,14 @@
🎲 Создать кейс
-
- - -
-
- - -
+
+
-
- - -
-
- - -
-
-
- - +
+
+
📋 Предметы кейса
@@ -116,14 +99,8 @@
➕ Добавить кейс в секцию

Секция:

-
- - -
-
- - -
+
+
@@ -131,14 +108,8 @@
➕ Новая секция
-
- - -
-
- - -
+
+
{% endblock %} @@ -157,98 +128,44 @@ {% block scripts %} {% endblock %} diff --git a/templates/admin/dashboard.html b/templates/admin/dashboard.html index 6f87e07..fd48237 100644 --- a/templates/admin/dashboard.html +++ b/templates/admin/dashboard.html @@ -44,9 +44,9 @@
{{ rpu_count }}
Всего записей
{{ "%.1f"|format(avg_rpu) }}%
Средний уровень
-
{{ lucky_count }}
🍀 Везучих
-
{{ normal_count }}
📊 Обычных
-
{{ unlucky_count }}
🌧️ Невезучих
+
{{ lucky_count }}
🍀 Везучих
+
{{ normal_count }}
📊 Обычных
+
{{ unlucky_count }}
🌧️ Невезучих
{{ "%.0f"|format(total_spent) }} ₽
Потрачено всего
{% else %} diff --git a/templates/admin/user_detail.html b/templates/admin/user_detail.html index dc898db..3511418 100644 --- a/templates/admin/user_detail.html +++ b/templates/admin/user_detail.html @@ -2,7 +2,7 @@ {% block title %}{{ target_user.username }} — Админ-панель{% endblock %} {% block nav_users %}active{% endblock %} {% block page_title %} - 👤 {{ target_user.username }} + {{ target_user.username }} {% if target_user.is_admin %}Админ{% endif %} {% if target_user.is_banned %}Забанен{% endif %} {% endblock %} @@ -11,62 +11,63 @@ {% endblock %} {% block content %} -
+
Баланс
{{ "%.0f"|format(target_user.balance) }} ₽
+
Предметов
{{ inventory|length }}
+
Открытий кейсов
{{ total_openings }}
+
Контрактов
{{ total_contracts }}
+
-
-
🎲 РПУ (Режим Персонального Угнетения)
-
-
--
Уровень
-
--
Множитель
-
--
Потрачено
-
--
Открыто
-
--
Авто
+
RPU (Режим Персонального Угнетения)
+
+
--
Уровень
+
--
Множитель
+
--
Потрачено
+
--
Открыто
+
--
Авто
-
- - - - - +
+ + + + +
-
-
🔧 Действия
-
- - +
Действия
+
+ + {% if target_user.id != user.id %} - + {% endif %}
-
-
🎒 Инвентарь (последние 50)
+
Инвентарь (последние 50)
@@ -78,7 +79,7 @@ {% endfor %} @@ -89,11 +90,10 @@ {% endblock %} {% block modals %} -
-
💰 Изменить баланс
-

+

Изменить баланс
+

Текущий: {{ "%.2f"|format(target_user.balance) }} ₽

@@ -103,9 +103,9 @@
@@ -115,10 +115,9 @@
-
-
🎁 Выдать предмет
+
Выдать предмет
@@ -130,14 +129,13 @@
-
-
⚙️ Настройка РПУ
+
Настройка RPU
@@ -150,7 +148,7 @@ {% block extra_styles %} -
+
- ← Назад к списку кейсов - -
-
-
-

📦 {{ case_display_name }}

-

{{ total_items }} предметов в кейсе

-
-
- 🔑 {{ "%.0f"|format(case_price) }} ₽ за шт. -
+ ← Назад к списку кейсов + +
+
+

{{ case_display_name }}

+

{{ total_items }} предметов в кейсе

- -
- {% if user %} -
- -
-
-
- Итого: {{ "%.0f"|format(case_price) }} ₽ -
+ 🔑 {{ "%.0f"|format(case_price) }} ₽ за шт. +
+ +
+ {% if user %} +
+ Открыть: +
+
+
+ {{ "%.0f"|format(case_price) }} ₽ - - {% else %} -
- 🔒 Войдите в аккаунт, чтобы открывать кейсы - Войти - Регистрация -
- {% endif %} +
+ {% else %} +
+ 🔒 Войдите в аккаунт, чтобы открывать кейсы + Войти + Регистрация +
+ {% endif %}
- -
- + +
- +
- -
-

📋 Содержимое кейса ({{ total_items }} предметов)

-
- - {% for rarity in sorted_rarities %} - - {% endfor %} -
+ +
+

📋 Содержимое кейса ({{ total_items }} предметов)

+
+ +
+ {% for rarity in sorted_rarities %} -
-

- {{ rarity }} - ({{ items_by_rarity[rarity]|length }}) + + {% endfor %} +

+ + {% for rarity in sorted_rarities %} +
+
+

+ {{ rarity }}

- -
- {% for item in items_by_rarity[rarity] %} -
- ({{ items_by_rarity[rarity]|length }}) +
+ +
+ {% for item in items_by_rarity[rarity] %} +
+
+ {{ item.name }} -
{{ item.name }}
-
+ onerror="this.src='/static/placeholder.png'" + style="width:100%;height:100px;object-fit:contain;margin-bottom:6px;"> +
{{ item.name }}
+
{{ item.type }} {{ "%.2f"|format(item.probability) }}%
-
+
Float: {{ "%.2f"|format(item.min_float) }} - {{ "%.2f"|format(item.max_float) }}
{% if item.min_price and item.max_price %} -
+
{% if item.min_price == item.max_price %} {{ "%.0f"|format(item.min_price) }} ₽ {% else %} @@ -396,11 +356,11 @@
{% endif %}
- {% endfor %}
+ {% endfor %}
- {% endfor %}
+ {% endfor %}
@@ -534,9 +494,9 @@ const totalPrice = casePrice * currentOpenCount; const priceElement = document.getElementById('totalPriceDisplay'); const openButton = document.getElementById('openButton'); - if (priceElement) priceElement.innerHTML = `Итого: ${totalPrice.toLocaleString()} ₽`; + if (priceElement) priceElement.textContent = `${totalPrice.toLocaleString()} ₽`; if (openButton) { - openButton.style.background = userBalance < totalPrice ? 'var(--danger-color)' : 'var(--primary-color)'; + openButton.style.background = userBalance < totalPrice ? 'var(--danger)' : ''; openButton.title = userBalance < totalPrice ? 'Недостаточно средств' : ''; } } @@ -1144,7 +1104,7 @@

😕 Увы, топ-дропа не оказалось

Открыто ${currentOpenCount} кейсов, но ничего ценного не выпало.

-

💰 Шлак (${trashItems.length} предметов) автоматически продан.

+

💰 Шлак (${trashItems.length} предметов) автоматически продан.

@@ -1161,7 +1121,7 @@
-
+
💰 Шлак (${trashItems.length} предметов) автоматически продан
`; @@ -1458,449 +1418,449 @@ }).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 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'; - const color = getRarityColor(item.rarity); - div.style.borderColor = color; - div.style.borderWidth = '2px'; - div.style.borderStyle = 'solid'; + div.innerHTML = ` + +
${item.name.substring(0, 25)}
+
${item.rarity}
+ `; + track.appendChild(div); + }); - div.innerHTML = ` - -
${item.name.substring(0, 25)}
-
${item.rarity}
- `; - 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'; + 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; - // 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; + let currentPos = containerWidth + 100; track.style.transform = `translateX(${currentPos}px)`; + track.style.willChange = 'transform'; - // Звук: определяем какой предмет сейчас в центре - 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); + // 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 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(); + const prevPos = currentPos; + currentPos = (containerWidth + 100) - ((containerWidth + 100) - finalPos) * easeOut; + track.style.transform = `translateX(${currentPos}px)`; - // 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'; + // Звук: определяем какой предмет сейчас в центре + const centerX = -currentPos + targetOffset + itemTotalWidth / 2; + const tickIndex = Math.floor(centerX / itemTotalWidth); + if (tickIndex >= 0 && tickIndex < totalItems && tickIndex !== lastTickIndex) { + SoundManager.wheelSpin(); + lastTickIndex = tickIndex; } - - 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 = ` - -
${item.name.substring(0, 12)}
- `; - track.appendChild(div); + 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); }); - - 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++; + 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 = ` + +
${item.name.substring(0, 12)}
+ `; + 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(); } - }); - - let totalValue = results.reduce((sum, item) => sum + (item.price || 100), 0); - - let html = ` -
-
🎉 Получено (${results.length})
-
- - -
-
-
- `; - - Object.values(grouped).forEach((item, idx) => { - const color = getRarityColor(item.rarity); - html += ` -
-
- -
-
${item.name}
-
- ${item.rarity} -
- + + 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 = ` +
+
🎉 Получено (${results.length})
+
+ +
- ${item.count > 1 ? `x${item.count}` : ''}
+
`; - }); - - html += `
`; - - 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) { - if (!confirm('Продать этот предмет?')) 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) { - alert('Предмет не найден в инвентаре'); + Object.values(grouped).forEach((item, idx) => { + const color = getRarityColor(item.rarity); + html += ` +
+
+ +
+
${item.name}
+
+ ${item.rarity} +
+ +
+ ${item.count > 1 ? `x${item.count}` : ''} +
+ `; + }); + + html += `
`; + + 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) { + if (!confirm('Продать этот предмет?')) 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) { + alert('Предмет не найден в инвентаре'); + 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) { + await refreshUserBalance(); + await refreshInventoryAjax(); + // Remove the sold item card from display + 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 { + alert(data.error || 'Ошибка при продаже'); + } + } catch (error) { + alert('Ошибка соединения'); + } + } + + async function sellAllResults() { + if (!window.lastOpenedItems || window.lastOpenedItems.length === 0) { + alert('Нет предметов для продажи'); return; } - const formData = new FormData(); - formData.append('inventory_id', inventoryItem.id); + const total = window.lastOpenedItems.reduce((sum, i) => sum + (i.price || 100), 0); + if (!confirm(`Продать все выпавшие предметы за ${total.toLocaleString()} ₽?`)) return; - const sellResponse = await fetch('/web/api/inventory/sell', { - method: 'POST', - body: formData - }); - - const data = await sellResponse.json(); - - if (data.success) { - await refreshUserBalance(); - await refreshInventoryAjax(); - // Remove the sold item card from display - 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; + 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); } } - } else { - alert(data.error || 'Ошибка при продаже'); - } - } catch (error) { - alert('Ошибка соединения'); - } - } - - async function sellAllResults() { - if (!window.lastOpenedItems || window.lastOpenedItems.length === 0) { - alert('Нет предметов для продажи'); - return; - } - - const total = window.lastOpenedItems.reduce((sum, i) => sum + (i.price || 100), 0); - if (!confirm(`Продать все выпавшие предметы за ${total.toLocaleString()} ₽?`)) 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) { + alert('Предметы не найдены в инвентаре'); + return; } - } - - if (inventoryIds.length === 0) { - alert('Предметы не найдены в инвентаре'); - 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(); + + 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) { - await refreshUserBalance(); - await refreshInventoryAjax(); - // Clear results and reset UI - const resultsDiv = document.getElementById('openingResults'); - resultsDiv.style.display = 'none'; - resultsDiv.innerHTML = ''; - window.lastOpenedItems = []; - } else { - alert(data.error || 'Ошибка при продаже'); + if (data.success) { + await refreshUserBalance(); + await refreshInventoryAjax(); + // Clear results and reset UI + const resultsDiv = document.getElementById('openingResults'); + resultsDiv.style.display = 'none'; + resultsDiv.innerHTML = ''; + window.lastOpenedItems = []; + } else { + alert(data.error || 'Ошибка при продаже'); + } + } catch (error) { + alert('Ошибка соединения'); } - } catch (error) { - alert('Ошибка соединения'); } - } - - 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'; - } - }); - - - - - - -{% if user %}{% include '_activity_sidebar.html' %}{% endif %} - - \ No newline at end of file + + 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'; + } + }); + + + + + + + {% if user %}{% include '_activity_sidebar.html' %}{% endif %} + + diff --git a/templates/cases.html b/templates/cases.html index 68a4bc2..5f4ec81 100644 --- a/templates/cases.html +++ b/templates/cases.html @@ -3,181 +3,33 @@ - Кейсы - CS2 Simulator + Кейсы — CS2 Simulator - -
+
- @@ -256,4 +100,4 @@ {% if user %}{% include '_activity_sidebar.html' %}{% endif %} - \ No newline at end of file + diff --git a/templates/contracts.html b/templates/contracts.html index d9ea34e..c94e297 100644 --- a/templates/contracts.html +++ b/templates/contracts.html @@ -9,25 +9,25 @@ - - -
-
-

🔄 Trade Up Контракт

-

Выберите 10 предметов одинаковой редкости и типа

-
- - {% if inventory_items and inventory_items|length >= 10 %} -
- -
-
- - - - - +
+
+
+
+

🔄 Trade Up Контракт

+

Выберите 10 предметов одинаковой редкости и типа

-
- -
-
-

📋 Контракт

- 0/10 -
-
- {% for i in range(10) %} -
- {{ i+1 }} + {% if inventory_items and inventory_items|length >= 10 %} +
+ +
+
+ + + + +
- {% endfor %} +
-
Выберите предмет из инвентаря
-
- - - {% if knife_count >= 10 %} - - {% endif %} + + +
+
+ 📋 Контракт + 0/10 +
+
+ {% for i in range(10) %} +
+ {{ i+1 }} +
+ {% endfor %} +
+
Выберите предмет из инвентаря
+
+ + + {% if knife_count >= 10 %} + + {% endif %} +
-
- {% else %} -
- {% if user %} -
📭
-

Недостаточно предметов

-

Нужно минимум 10 предметов одинаковой редкости и типа

- Открыть кейсы + + {% if not user %} +
+
🔒
+
Контракты доступны только авторизованным
+
Войдите в аккаунт, чтобы просматривать инвентарь и заключать контракты
+ +
+ {% endif %} {% else %} -
🔒
-

Контракты доступны только авторизованным

-

Войдите в аккаунт, чтобы просматривать инвентарь и заключать контракты

- Войти - Регистрация +
+ {% if user %} +
📭
+
Недостаточно предметов
+
Нужно минимум 10 предметов одинаковой редкости и типа
+ Открыть кейсы + {% else %} +
🔒
+
Контракты доступны только авторизованным
+
Войдите в аккаунт, чтобы просматривать инвентарь и заключать контракты
+ Войти + Регистрация + {% endif %} +
{% endif %}
- {% endif %}
- -
-
-
📜 TRADE UP CONTRACT
-
CS2 Weapon Case — проверка подлинности
-
-
-
-
- - + + - -
-
-
+ + + + + - - - - {% if user %}{% include '_activity_sidebar.html' %}{% endif %} diff --git a/templates/crash.html b/templates/crash.html index fa13764..b71fae6 100644 --- a/templates/crash.html +++ b/templates/crash.html @@ -3,132 +3,76 @@ - Crash - CS2 Simulator + Crash — CS2 Simulator -
-
-
+
+
+
-
+
Ожидание...
-
Следующий раунд скоро начнётся
+
Следующий раунд скоро начнётся
-
+
-
-
-

💰 Сделать ставку

-
- +
+
+

💰 Сделать ставку

+
+
-
+
- - - -
-
-
-
-
- 1.00x - 1.00x -
+ + + +
-
-

👥 Ставки

-
-
- Ожидание ставок... -
-
+
+

👥 Ставки

+
Ожидание ставок...
@@ -138,380 +82,118 @@ {% include '_activity_sidebar.html' %} diff --git a/templates/index.html b/templates/index.html index 6bfc024..578f072 100644 --- a/templates/index.html +++ b/templates/index.html @@ -9,50 +9,49 @@ -
+

CS2 Trade-Up Simulator

Открывай кейсы, собирай скины и создавай контракты

- -
-
-
📦
-

Открывай кейсы

-

Испытай удачу и получи редкие скины

+
+
+
📦
+

Открывай кейсы

+

Испытай удачу и получи редкие скины

-
-
🔄
-

Создавай контракты

-

Обменивай 10 скинов на один более редкий

+
+
🔄
+

Создавай контракты

+

Обменивай 10 скинов на один более редкий

-
-
📊
-

Собирай коллекцию

-

Отслеживай свой прогресс и статистику

+
+
📊
+

Собирай коллекцию

+

Отслеживай свой прогресс и статистику

-
-
+ - \ No newline at end of file + diff --git a/templates/inventory.html b/templates/inventory.html index 423fda6..301e107 100644 --- a/templates/inventory.html +++ b/templates/inventory.html @@ -3,276 +3,70 @@ - Инвентарь - CS2 Simulator + Инвентарь — CS2 Simulator - -
+
-
+
-

🎒 Инвентарь

-

Всего предметов: {{ inventory_items|length }}

+

🎒 Инвентарь

+

Всего предметов: {{ inventory_items|length }}

- -
-
- - - -
- -
- - -
+
+ + + + +
- -
-
- - - - - - - -
+ +
+ + + +
- + {% if inventory_items %} -
+
{% for item in inventory_items %} -
- -
- {{ item.name }} +
+ {{ item.name }}
-
-
{{ item.name }}
-
- {{ item.rarity }} - Float: {{ "%.6f"|format(item.float) }} -
-
- {{ item.type }} - {{ item.wear }} -
-
- 💰 {{ "%.0f"|format(item.price_rub or 100) }} ₽ -
-
- -
+
{{ item.name }}
+
+ {{ item.rarity }} + Float: {{ "%.6f"|format(item.float) }} +
+
{{ item.type }} / {{ item.wear }}
+
+ 💰 {{ "%.0f"|format(item.price_rub or 100) }} ₽ +
{% endfor %}
{% else %} -
-
📭
-

Ваш инвентарь пуст

-

Откройте кейсы, чтобы получить первые предметы!

+
+
📭
+
Ваш инвентарь пуст
+
Откройте кейсы, чтобы получить первые предметы!
Открыть кейсы
{% endif %}
- - -
IDНазваниеРедкостьFloat
{{ item.rarity }} {{ "%.4f"|format(item.float_value) }} - +