ui/sonicdazeoverlay.razor.scss
// SONIC DAZE — soft vision, not lost vision.
//
// ⚠️ THE BLUR ITSELF IS SET FROM CODE, not here. `backdrop-filter` is written to Style every frame
// because its strength is the whole point; the rules below are only the things that do not change.

.daze
{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;

    // ⚠️ ABOVE the napalm overlay (42), below nothing the player has to read. A daze is an attack
    // in progress rather than a warning about one, so it must not sit under heat haze — but the
    // HUD has to stay legible through it, which is why this is a layer and not a full-screen tint.
    z-index: 44;

    .layer
    {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        opacity: 0;
    }

    // ⛔ THE BLUR PANEL HAS NO BACKGROUND OF ITS OWN. `backdrop-filter` operates on what is already
    // rendered behind it; giving this a fill would hide the very thing it is meant to be blurring,
    // and the effect would read as a flat pane of colour.
    .soft
    {
        // A slow drift, so the softness breathes instead of sitting still. Small — this is a
        // disorientation, and anything larger becomes motion sickness.
        animation: daze-drift 2.6s ease-in-out infinite;
    }

    // The cold ring at the edges. This one DOES have a fill: it is the tell that something was
    // done to you, as opposed to the picture simply going out of focus.
    .edge
    {
        background-image: radial-gradient(
            ellipse at center,
            rgba(150, 190, 240, 0) 44%,
            rgba(150, 190, 240, 0.30) 78%,
            rgba(96, 140, 200, 0.62) 100%
        );

        mix-blend-mode: screen;
        animation: daze-press 1.7s ease-in-out infinite;
    }
}

@keyframes daze-drift
{
    0%   { transform: scale(1.000) translateX(0px); }
    50%  { transform: scale(1.012) translateX(3px); }
    100% { transform: scale(1.000) translateX(0px); }
}

// ⛔ TRANSFORM ONLY — NEVER `opacity` IN A KEYFRAME ON A PANEL WHOSE OPACITY CODE DRIVES. A running
// CSS animation beats the inline style, so `Edge.Style.Opacity = 0` did nothing and this blue ring
// sat on the player's screen permanently from the moment `SurvivalHud` mounted the overlay —
// visible in a fresh game, with no Shrieker anywhere, and no way to turn it off short of
// `nz_daze_overlay 0`.
//
// ⚠️ THE RULE WAS ALREADY WRITTEN DOWN IN THIS FOLDER AND I BROKE IT ANYWAY.
// `DamageOverlay.razor.scss` line 3: *"Opacity is driven per frame from code, NOT by a keyframe."*
// The strength of every overlay in this project is written from C# every frame, so a keyframe may
// MOVE a layer but must never FADE one. See INSTRUCTIONS.md §29.
@keyframes daze-press
{
    0%   { transform: scale(1.06); }
    50%  { transform: scale(1.00); }
    100% { transform: scale(1.06); }
}