/*
 * vibe.css — анимационный слой для ТОН/STORM
 * <link rel="stylesheet" href="/static/css/vibe.css">
 * Подключать последним в <head>.
 *
 * КРИТИЧНО:
 *   — НЕ используем body::after с transform-анимацией
 *     (ломает position:fixed у плеера и хедера)
 *   — НЕ меняем position у #left-rail
 *     (он fixed в base.css)
 *   — НЕ добавляем .fragment на #player и .main-header
 *     (transform на fixed-элементах = баги позиционирования)
 */


/* ════════════════════════════════════════════
   GRAIN — зернистость плёнки
   ─────────────────────────────────────────
   mix-blend-mode: overlay — смешивается
   с фоном, не создаёт тёмный блок поверх.
   Только в rail и right_panel.
════════════════════════════════════════════ */

#left-rail::after,
#right_panel::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.80' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    opacity: 0.18;
    mix-blend-mode: overlay;
    pointer-events: none;
    z-index: 9999;
    border-radius: inherit;
    animation: grain-flicker 0.5s steps(1) infinite;
}

body[data-theme="light"] #left-rail::after,
body[data-theme="light"] #right_panel::after {
    opacity: 0.12;
    mix-blend-mode: multiply;
}

@keyframes grain-flicker {
    0%   { background-position: 0 0; }
    20%  { background-position: -30px -40px; }
    40%  { background-position: 20px 15px; }
    60%  { background-position: -15px 30px; }
    80%  { background-position: 40px -20px; }
    100% { background-position: -10px 10px; }
}

#right_panel {
    position: relative;
}


/* ════════════════════════════════════════════
   FRAGMENT ENTRY
   ─────────────────────────────────────────
   Добавить в HTML: class="fragment" data-chaos="wild"
   Уровни: gentle | medium | big | wild
   JS (vibe.js) вызывает Vibe.assemble() автоматически.
════════════════════════════════════════════ */

.fragment {
    opacity: 0;
    transform:
        translateX(var(--fx, 0px))
        translateY(var(--fy, 0px))
        rotate(var(--fr, 0deg))
        scale(var(--fs, 0.75));
    filter: blur(var(--fb, 4px));
    transition:
        opacity   0.65s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.65s cubic-bezier(0.16, 1, 0.3, 1),
        filter    0.50s ease;
    transition-delay: var(--fd, 0ms);
    will-change: transform, opacity, filter;
}

.fragment.assembled {
    opacity: 1;
    transform: translateX(0) translateY(0) rotate(0deg) scale(1);
    filter: blur(0px);
}


/* ════════════════════════════════════════════
   HEADER — только fade, без transform
   (transform ломает translateX(-50%) в base.css)
════════════════════════════════════════════ */

.main-header {
    animation: header-fade 0.4s ease both;
}

@keyframes header-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}


/* ════════════════════════════════════════════
   LEFT RAIL — элементы влетают слева
════════════════════════════════════════════ */

#left-rail .lr-logo,
#left-rail .lr-user,
#left-rail .lr-nav .lr-item {
    opacity: 0;
    transform: translateX(-20px);
    animation: rail-in 0.55s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

#left-rail .lr-logo                      { animation-delay: 0.05s; }
#left-rail .lr-user                      { animation-delay: 0.12s; }
#left-rail .lr-nav .lr-item:nth-child(1) { animation-delay: 0.18s; }
#left-rail .lr-nav .lr-item:nth-child(2) { animation-delay: 0.23s; }
#left-rail .lr-nav .lr-item:nth-child(3) { animation-delay: 0.28s; }
#left-rail .lr-nav .lr-item:nth-child(4) { animation-delay: 0.33s; }
#left-rail .lr-nav .lr-item:nth-child(5) { animation-delay: 0.38s; }
#left-rail .lr-nav .lr-item:nth-child(6) { animation-delay: 0.43s; }
#left-rail .lr-nav .lr-item:nth-child(7) { animation-delay: 0.48s; }
#left-rail .lr-nav .lr-item:nth-child(8) { animation-delay: 0.53s; }
#left-rail .lr-nav .lr-item:nth-child(9) { animation-delay: 0.58s; }

@keyframes rail-in {
    to { opacity: 1; transform: translateX(0); }
}


/* ════════════════════════════════════════════
   PLAYER AMBIENT GLOW
════════════════════════════════════════════ */

#player::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    height: 90px;
    background: linear-gradient(
        to top,
        rgba(68, 217, 149, 0.09),
        transparent
    );
    pointer-events: none;
    opacity: 0;
    transition: opacity 1.4s ease;
}

#player.playing::before {
    opacity: 1;
    animation: player-breathe 3.5s ease-in-out infinite;
}

@keyframes player-breathe {
    0%, 100% { opacity: 0.3; }
    50%       { opacity: 1;  }
}

body[data-theme="light"] #player::before {
    background: linear-gradient(to top, rgba(47,201,135,0.09), transparent);
}


/* ════════════════════════════════════════════
   GLITCH HOVER — RGB-сдвиг на карточках
════════════════════════════════════════════ */

.vibe-glitch {
    position: relative;
    isolation: isolate;
}

.vibe-glitch::before,
.vibe-glitch::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    opacity: 0;
    pointer-events: none;
    z-index: 1;
}

.vibe-glitch::before {
    box-shadow: -3px 0 0 rgba(255, 0, 60, 0.4);
    mix-blend-mode: screen;
}

.vibe-glitch::after {
    box-shadow: 3px 0 0 rgba(0, 220, 255, 0.4);
    mix-blend-mode: screen;
}

.vibe-glitch:hover::before,
.vibe-glitch:hover::after {
    opacity: 1;
    animation: glitch-pulse 0.35s steps(2) forwards;
}

@keyframes glitch-pulse {
    0%   { opacity: 1; }
    60%  { opacity: 0.5; }
    100% { opacity: 0; }
}


/* ════════════════════════════════════════════
   MAGNETIC
════════════════════════════════════════════ */

.vibe-magnetic {
    transition: transform 0.3s cubic-bezier(0.23, 1, 0.32, 1);
    will-change: transform;
}


/* ════════════════════════════════════════════
   HOVER LIFT
════════════════════════════════════════════ */

.vibe-lift {
    transition:
        transform  0.25s cubic-bezier(0.23, 1, 0.32, 1),
        box-shadow 0.25s cubic-bezier(0.23, 1, 0.32, 1);
}

.vibe-lift:hover {
    transform: translateY(-3px);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
}


/* ════════════════════════════════════════════
   SCANLINE
════════════════════════════════════════════ */

#vibe-scanline {
    position: fixed;
    left: 0; right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(68,217,149,0.35), transparent);
    pointer-events: none;
    z-index: 9992;
    opacity: 0;
}

#vibe-scanline.flash {
    animation: scanline-flash 0.55s ease-out forwards;
}

@keyframes scanline-flash {
    0%   { opacity: 0; }
    20%  { opacity: 1; }
    100% { opacity: 0; }
}


/* ════════════════════════════════════════════
   ПРОЧЕЕ
════════════════════════════════════════════ */

.vibe-scramble { user-select: none; }

::selection {
    background: rgba(68, 217, 149, 0.28);
    color: var(--text, #E6EDF3);
}

body[data-theme="light"] ::selection {
    background: rgba(47, 201, 135, 0.22);
    color: var(--text, #111418);
}

:focus-visible {
    outline: 2px solid var(--primary, #44D995);
    outline-offset: 3px;
    border-radius: 4px;
}