/*
    Ефектите на известията.

    ЕДИН файл за две места: страницата в OBS и прегледът в панела. Държа ги
    заедно нарочно — две копия на едни и същи ключови кадри се разминават
    още при първата промяна и прегледът почва да лъже.

    Всички пипат САМО transform, opacity, filter и background-position.
    Нито един не мести нещо в подредбата, затова браузърът ги дава на
    видеокартата и цената им в кадри е почти нулева.

    --мощ идва от правилото: 1 тихо, 5 крещящо. Всеки ефект я ползва
    различно — някъде е яркост, другаде брой или скорост.
    --accent е основният цвят, --ц2 вторият.
*/

.fx-glow, .fx-neon, .fx-scan, .fx-shake,
.fx-glitch, .fx-crt, .fx-stripes,
.fx-rainbow, .fx-pulse, .fx-flicker,
.fx-tilt, .fx-aurora, .fx-runner {
  --мощ: 3;
}

/* Сияние: рамката диша. */
.fx-glow {
    animation: fxGlow calc(2.4s / (0.6 + var(--мощ) * 0.15)) ease-in-out infinite;
}
@keyframes fxGlow {
    0%, 100% { box-shadow: 0 0 calc(10px * var(--мощ)) -4px var(--accent, var(--primary)); }
    50%      { box-shadow: 0 0 calc(26px * var(--мощ)) 2px var(--accent, var(--primary)); }
}

/* Неон: кант от два цвята, който потрепва като истинска тръба —
   неравномерно, затова кадрите не са на равни разстояния. */
.fx-neon {
    border-color: var(--accent, var(--primary));
    animation: fxNeon 3.2s linear infinite;
}
@keyframes fxNeon {
    0%, 18%, 22%, 54%, 58%, 100% {
        box-shadow: 0 0 calc(5px * var(--мощ)) var(--accent, var(--primary)),
                    inset 0 0 calc(1.2px * var(--мощ)) var(--ц2);
        filter: none;
    }
    20%, 56% {
        box-shadow: 0 0 calc(2px * var(--мощ)) var(--ц2);
        filter: brightness(0.82);
    }
}

/* Сканиращ лъч: светъл наклонен лъч минава през известието.
   Отделен слой, за да не пипа фона на самото известие. */
.fx-scan::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(105deg,
        transparent 38%,
        color-mix(in srgb, var(--accent, var(--primary)) calc(var(--мощ) * 14%), transparent) 50%,
        transparent 62%);
    background-size: 280% 100%;
    animation: fxScan calc(3.4s / (0.5 + var(--мощ) * 0.18)) linear infinite;
}
@keyframes fxScan {
    from { background-position: 140% 0; }
    to   { background-position: -140% 0; }
}

/* Разтърсване: къс удар при влизане, после мирува. Не се върти в кръг —
   известие, което трепери през цялото време, не се чете. */
.fx-shake { animation: fxShake calc(0.5s + var(--мощ) * 0.06s) cubic-bezier(.36,.07,.19,.97) 1; }
@keyframes fxShake {
    10%, 90% { transform: translate3d(calc(-1px * var(--мощ)), 0, 0); }
    20%, 80% { transform: translate3d(calc(2px * var(--мощ)), 0, 0); }
    30%, 50%, 70% { transform: translate3d(calc(-3px * var(--мощ)), 0, 0); }
    40%, 60% { transform: translate3d(calc(3px * var(--мощ)), 0, 0); }
    100% { transform: none; }
}

/* Накъсване: двата цвята се разминават за миг, като счупен сигнал. */
.fx-glitch { animation: fxGlitch 2.6s steps(1, end) infinite; }
@keyframes fxGlitch {
    0%, 86%, 100% { transform: none; filter: none; }
    88% {
        transform: translate3d(calc(-1px * var(--мощ)), 0, 0);
        filter: drop-shadow(calc(2px * var(--мощ)) 0 0 var(--accent, var(--primary)))
                drop-shadow(calc(-2px * var(--мощ)) 0 0 var(--ц2));
    }
    90% { transform: translate3d(calc(1.5px * var(--мощ)), 0, 0); filter: none; }
    92% {
        transform: translate3d(calc(-0.5px * var(--мощ)), 0, 0);
        filter: drop-shadow(calc(-1px * var(--мощ)) 0 0 var(--ц2));
    }
}

/* Стар екран: линии пълзят нагоре. Чист градиент, без картинка. */
.fx-crt::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    /* Светли линии, не тъмни: известието е почти черно и тъмните
       линии върху него са невидими. */
    background: repeating-linear-gradient(
        to bottom,
        rgba(255, 255, 255, calc(0.022 * var(--мощ))) 0 1px,
        transparent 1px 3px);
    mix-blend-mode: screen;
    animation: fxCrt 1.6s linear infinite;
}
@keyframes fxCrt {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(0, -3px, 0); }
}

/* Движещи се ивици: диагонална лента под съдържанието. */
.fx-stripes::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: -1;
    /* Слабо нарочно. Ивиците са текстура ПОД текста — щом почнат да
       се четат по-лесно от него, ефектът е сбъркан. */
    background: repeating-linear-gradient(
        -45deg,
        color-mix(in srgb, var(--accent, var(--primary)) calc(var(--мощ) * 2.4%), transparent) 0 14px,
        color-mix(in srgb, var(--ц2) calc(var(--мощ) * 1.3%), transparent) 14px 28px);
    background-size: 200% 200%;
    animation: fxStripes calc(5s / (0.4 + var(--мощ) * 0.2)) linear infinite;
}
@keyframes fxStripes {
    from { background-position: 0 0; }
    to   { background-position: 56px 0; }
}


/* ================== Втора вълна ================== */

/*
    Дъга: кантът обикаля целия тон. Нарочно НЕ слуша избрания цвят —
    това е целият ефект. Описанието в галерията го казва, за да не
    изглежда като счупено.
*/
.fx-rainbow {
  animation: fxRainbow calc(6s / (0.5 + var(--мощ) * 0.18)) linear infinite;
}
@keyframes fxRainbow {
    0%   { border-color: #F4564A; box-shadow: 0 0 calc(5px * var(--мощ)) #F4564A; }
    17%  { border-color: #F0B429; box-shadow: 0 0 calc(5px * var(--мощ)) #F0B429; }
    33%  { border-color: #C5F24E; box-shadow: 0 0 calc(5px * var(--мощ)) #C5F24E; }
    50%  { border-color: #10B981; box-shadow: 0 0 calc(5px * var(--мощ)) #10B981; }
    67%  { border-color: #2096F8; box-shadow: 0 0 calc(5px * var(--мощ)) #2096F8; }
    83%  { border-color: #7C4DF5; box-shadow: 0 0 calc(5px * var(--мощ)) #7C4DF5; }
    100% { border-color: #F4564A; box-shadow: 0 0 calc(5px * var(--мощ)) #F4564A; }
}

/*
    Пулс: бие като сърце — две бързи свивания, после пауза. Различава се
    от сиянието по това, че МЪРДА, а не свети; двете се четат различно
    дори в ъгъла на екрана.
*/
.fx-pulse {
  animation: fxPulse calc(1.6s / (0.6 + var(--мощ) * 0.1)) ease-in-out infinite;
}
@keyframes fxPulse {
    0%, 40%, 100% { transform: scale(1); }
    12% { transform: scale(calc(1 + 0.012 * var(--мощ))); }
    24% { transform: scale(1); }
    32% { transform: scale(calc(1 + 0.008 * var(--мощ))); }
}

/*
    Угасваща крушка: неравномерно премигване. Кадрите са нарочно на
    неравни разстояния — равномерното мигане изглежда като анимация,
    неравномерното като повреда.
*/
.fx-flicker {
  animation: fxFlicker 3.1s linear infinite;
}
@keyframes fxFlicker {
    0%, 4%, 7%, 38%, 41%, 72%, 100% { opacity: 1; }
    5%  { opacity: calc(1 - 0.12 * var(--мощ)); }
    6%  { opacity: 1; }
    39% { opacity: calc(1 - 0.16 * var(--мощ)); }
    40% { opacity: calc(1 - 0.05 * var(--мощ)); }
    73% { opacity: calc(1 - 0.14 * var(--мощ)); }
    74% { opacity: 1; }
    75% { opacity: calc(1 - 0.08 * var(--мощ)); }
}

/*
    Люлка: триизмерно полюляване. perspective е на самото известие,
    затова не трябва нищо от родителя.
*/
.fx-tilt {
  /* perspective() е В трансформацията; свойството perspective важи за
     ДЕЦАТА и тук не прави нищо. */
  animation: fxTilt calc(5s / (0.5 + var(--мощ) * 0.14)) ease-in-out infinite;
}
@keyframes fxTilt {
    0%, 100% { transform: perspective(700px) rotateX(calc(1deg * var(--мощ) * 0.5)) rotateY(calc(-1deg * var(--мощ) * 0.7)); }
    50%      { transform: perspective(700px) rotateX(calc(-1deg * var(--мощ) * 0.5)) rotateY(calc(1deg * var(--мощ) * 0.7)); }
}

/*
    Сияйна завеса: два меки облака зад известието, които бавно се местят.
    Слоят е под съдържанието (z-index:-1) и затова иска isolation на
    .alert — което вече го има.
*/
.fx-aurora::before {
    content: '';
    position: absolute;
    inset: calc(-6px * var(--мощ));
    border-radius: inherit;
    pointer-events: none;
    z-index: -1;
    filter: blur(calc(6px + 2px * var(--мощ)));
    opacity: calc(0.12 * var(--мощ));
    background:
        radial-gradient(45% 60% at 22% 30%, var(--accent, var(--primary)), transparent 70%),
        radial-gradient(45% 60% at 78% 70%, var(--ц2), transparent 70%);
    background-size: 220% 220%;
    animation: fxAurora calc(9s / (0.5 + var(--мощ) * 0.12)) ease-in-out infinite;
}
@keyframes fxAurora {
    0%, 100% { background-position: 0% 50%, 100% 50%; }
    50%      { background-position: 100% 50%, 0% 50%; }
}

/*
    Тичащ кант: светло петно обикаля рамката. Прави се с conic-gradient
    върху слой, който се върти — така петното върви по ВСИЧКИ страни,
    вместо да отскача по ъглите, както става с преместване на фона.
*/
/*
    Ъгълът се регистрира като истинско свойство, за да може да се анимира.
    Без @property браузърът го смята за текст и преходът не тръгва —
    тогава ефектът просто стои неподвижен, което е приемливо, не счупено.

    Внимание: НЕ се върти самият слой. Той е правоъгълник колкото
    известието и въртенето му би изкарало ъглите извън кадъра. Върти се
    само ъгълът на градиента, а слоят стои на място.
*/
@property --ъгъл {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

.fx-runner::after {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: inherit;
    pointer-events: none;
    padding: 2px;
    /* Петното е широко 70°, не 56°: на широко известие тесният ъгъл
       се свива до няколко пиксела и ефектът не се забелязва. */
    background: conic-gradient(
        from var(--ъгъл),
        transparent 0deg,
        color-mix(in srgb, var(--accent, var(--primary)) 60%, transparent) 14deg,
        var(--accent, var(--primary)) 34deg,
        var(--ц2) 48deg,
        color-mix(in srgb, var(--ц2) 40%, transparent) 62deg,
        transparent 76deg,
        transparent 360deg);
    /* Остава само кантът: маската изрязва вътрешността. */
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    opacity: calc(0.4 + 0.12 * var(--мощ));
    filter: drop-shadow(0 0 calc(1px * var(--мощ)) var(--accent, var(--primary)));
    animation: fxRunner calc(4s / (0.4 + var(--мощ) * 0.2)) linear infinite;
}
@keyframes fxRunner {
    to { --ъгъл: 360deg; }
}

/*
    Редът с останалите при сливане: «и още Иван, Петър и 7 души».
    По-дребен от текста нарочно — той е обяснение, не новината.
*/
.alert .още {
  font-size: 0.72em;
  opacity: 0.75;
  margin-top: -0.25em;
}
