As per your situation, the view online re-executes the AMPScript that's why **@today** picks up the current date. I had a similar situation and here is my solution. Although notice this method would have few seconds difference compared to the **@today** in your non-online version.

Having (true) within the Now() function falls back to the original time when the email was sent/previewed.

    %%[
    SET @today = Now(true)
    ]%%