Russian Caesar cipher The objective

Given a Russian text, encrypt it with Caesar cipher with key 16.

The basic Cyrillic alphabets

The basic Cyrillic alphabets are: (U+0410 – U+042F)

АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ


By the Caesar cipher, they are mapped to:

РСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЖЗИЙКЛМНОП


The small letters (U+0430 – U+044F) are also mapped likewise.

Note the absence of Ё.

Rules


Ё (U+0401) and ё (U+0451) are not considered basic, and are mapped to Х&#x308; (U+0425 U+0308) and х&#x308; (U+0445 U+0308), respectively.
Any other characters are preserved.


Example

The following sentence:

В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!


Is encrypted to:

Т зрйре оур цшы сл жшвагб? Фр, эю дрымиштлщ нъчхьяыпа!
JavaScript (ES6),  148 ... 110  108 bytes
Saved 12 bytes thanks to @Grimy!
This function applies some maths to the code points.
s=&gt;s.replace(/./g,s=&gt;String.fromCharCode(...(n=s.charCodeAt()-304)%80-1?[(n^16*(n&gt;0))+304]:[1060+n%48,776]))

Try it online!
How?
For each character in the input string, we define \$n\$ as its code point minus \$304\$.
 characters    | code points  | n
---------------+--------------+---------------
 А to Я        | 1040 to 1071 | 736 to 767
 а to я        | 1072 to 1103 | 768 to 799
 Ё             | 1025         | 721
 ё             | 1105         | 801
 ASCII         | 0 to 126     | -304 to -178

Then we apply the following logic:
// neither 'Ё' nor 'ё'?
n % 80 - 1 ?
  // output a single code point
  [
    // invert the case if this is a Cyrillic character
    (n ^ 16 * (n &gt; 0))
    // and restore the original offset
    + 304
  ]
:
  // output two code points
  [
    // the first one is either 1061 (Х) or 1093 (х)
    1060 + n % 48,
    // the 2nd one is the combining diaeresis
    776
  ]