diff --git a/Telegram/Resources/icons/mediaview/download.png b/Telegram/Resources/icons/mediaview/download.png
index 8866edd51..1c15631e5 100644
Binary files a/Telegram/Resources/icons/mediaview/download.png and b/Telegram/Resources/icons/mediaview/download.png differ
diff --git a/Telegram/Resources/icons/mediaview/download@2x.png b/Telegram/Resources/icons/mediaview/download@2x.png
index e5c3cf39f..36edd45eb 100644
Binary files a/Telegram/Resources/icons/mediaview/download@2x.png and b/Telegram/Resources/icons/mediaview/download@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/download@3x.png b/Telegram/Resources/icons/mediaview/download@3x.png
index 20e22ce52..ff3e812ec 100644
Binary files a/Telegram/Resources/icons/mediaview/download@3x.png and b/Telegram/Resources/icons/mediaview/download@3x.png differ
diff --git a/Telegram/Resources/icons/mediaview/next.png b/Telegram/Resources/icons/mediaview/next.png
index 8a1869c77..785425070 100644
Binary files a/Telegram/Resources/icons/mediaview/next.png and b/Telegram/Resources/icons/mediaview/next.png differ
diff --git a/Telegram/Resources/icons/mediaview/next@2x.png b/Telegram/Resources/icons/mediaview/next@2x.png
index 360fae2ce..81c5463d8 100644
Binary files a/Telegram/Resources/icons/mediaview/next@2x.png and b/Telegram/Resources/icons/mediaview/next@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/next@3x.png b/Telegram/Resources/icons/mediaview/next@3x.png
index 06197f226..8bc7d530c 100644
Binary files a/Telegram/Resources/icons/mediaview/next@3x.png and b/Telegram/Resources/icons/mediaview/next@3x.png differ
diff --git a/Telegram/Resources/icons/mediaview/next_shadow.png b/Telegram/Resources/icons/mediaview/next_shadow.png
new file mode 100644
index 000000000..0e432c95a
Binary files /dev/null and b/Telegram/Resources/icons/mediaview/next_shadow.png differ
diff --git a/Telegram/Resources/icons/mediaview/next_shadow@2x.png b/Telegram/Resources/icons/mediaview/next_shadow@2x.png
new file mode 100644
index 000000000..bcf60caa7
Binary files /dev/null and b/Telegram/Resources/icons/mediaview/next_shadow@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/next_shadow@3x.png b/Telegram/Resources/icons/mediaview/next_shadow@3x.png
new file mode 100644
index 000000000..48eb42399
Binary files /dev/null and b/Telegram/Resources/icons/mediaview/next_shadow@3x.png differ
diff --git a/Telegram/Resources/icons/mediaview/rotate.png b/Telegram/Resources/icons/mediaview/rotate.png
index 818a9b872..14104385b 100644
Binary files a/Telegram/Resources/icons/mediaview/rotate.png and b/Telegram/Resources/icons/mediaview/rotate.png differ
diff --git a/Telegram/Resources/icons/mediaview/rotate@2x.png b/Telegram/Resources/icons/mediaview/rotate@2x.png
index 1fc04404b..a846ec5bf 100644
Binary files a/Telegram/Resources/icons/mediaview/rotate@2x.png and b/Telegram/Resources/icons/mediaview/rotate@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/rotate@3x.png b/Telegram/Resources/icons/mediaview/rotate@3x.png
index 8369b477b..bfa39cd9f 100644
Binary files a/Telegram/Resources/icons/mediaview/rotate@3x.png and b/Telegram/Resources/icons/mediaview/rotate@3x.png differ
diff --git a/Telegram/Resources/icons/mediaview/shadow_bottom.png b/Telegram/Resources/icons/mediaview/shadow_bottom.png
index ccf350f2b..bd3799f32 100644
Binary files a/Telegram/Resources/icons/mediaview/shadow_bottom.png and b/Telegram/Resources/icons/mediaview/shadow_bottom.png differ
diff --git a/Telegram/Resources/icons/mediaview/shadow_bottom@2x.png b/Telegram/Resources/icons/mediaview/shadow_bottom@2x.png
index 6d0c8762d..72a588323 100644
Binary files a/Telegram/Resources/icons/mediaview/shadow_bottom@2x.png and b/Telegram/Resources/icons/mediaview/shadow_bottom@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/shadow_bottom@3x.png b/Telegram/Resources/icons/mediaview/shadow_bottom@3x.png
index 52ea5cfd1..3870e77d2 100644
Binary files a/Telegram/Resources/icons/mediaview/shadow_bottom@3x.png and b/Telegram/Resources/icons/mediaview/shadow_bottom@3x.png differ
diff --git a/Telegram/Resources/icons/mediaview/title_viewer_button_maximize.png b/Telegram/Resources/icons/mediaview/title_viewer_button_maximize.png
index 84df61a0a..0023e0551 100644
Binary files a/Telegram/Resources/icons/mediaview/title_viewer_button_maximize.png and b/Telegram/Resources/icons/mediaview/title_viewer_button_maximize.png differ
diff --git a/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@2x.png b/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@2x.png
index 77f55bfa9..8b8b2f1ad 100644
Binary files a/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@2x.png and b/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@3x.png b/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@3x.png
index 7dca97312..a36a73d54 100644
Binary files a/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@3x.png and b/Telegram/Resources/icons/mediaview/title_viewer_button_maximize@3x.png differ
diff --git a/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize.png b/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize.png
index 07e3a28e6..69cd79d4e 100644
Binary files a/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize.png and b/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize.png differ
diff --git a/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@2x.png b/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@2x.png
index 312be9534..cc39d499f 100644
Binary files a/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@2x.png and b/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@3x.png b/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@3x.png
index 5c5509cfa..11d3a9f35 100644
Binary files a/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@3x.png and b/Telegram/Resources/icons/mediaview/title_viewer_shadow_maximize@3x.png differ
diff --git a/Telegram/SourceFiles/media/view/media_view.style b/Telegram/SourceFiles/media/view/media_view.style
index 23116be7f..5130bc448 100644
--- a/Telegram/SourceFiles/media/view/media_view.style
+++ b/Telegram/SourceFiles/media/view/media_view.style
@@ -101,11 +101,17 @@ mediaviewVolumeToggle: IconButton(mediaviewControlsButton) {
 }
 mediaviewVolumeSkip: 4px;
 
-mediaviewLeft: icon {{ "mediaview/next-flip_horizontal", mediaviewControlFg }};
-mediaviewRight: icon {{ "mediaview/next", mediaviewControlFg }};
+mediaviewLeft: icon {
+	{ "mediaview/next_shadow-flip_horizontal", windowShadowFg }
+	{ "mediaview/next-flip_horizontal", mediaviewControlFg }
+};
+mediaviewRight: icon {
+	{ "mediaview/next_shadow", windowShadowFg }
+	{ "mediaview/next", mediaviewControlFg }
+};
 mediaviewSave: icon {{ "mediaview/download", mediaviewControlFg }};
 mediaviewRotate: icon {{ "mediaview/rotate", mediaviewControlFg }};
-mediaviewMore: icon {{ "mediaview/more", mediaviewControlFg }};
+mediaviewMore: icon {{ "title_menu_dots", mediaviewControlFg }};
 
 mediaviewFileRed: icon {
 	{ size(25px, 25px), mediaviewFileBg },
@@ -232,15 +238,13 @@ mediaviewThickFont: semiboldFont;
 mediaviewFont: normalFont;
 mediaviewTextStyle: defaultTextStyle;
 
-mediaviewTextLeft: 16px;
+mediaviewTextLeft: 14px;
 mediaviewTextSkip: 10px;
-mediaviewHeaderTop: 48px;
-mediaviewTextTop: 24px;
+mediaviewHeaderTop: 47px;
+mediaviewTextTop: 26px;
 
-mediaviewIconOpacity: 0.45;
-mediaviewIconOverOpacity: 1.;
 mediaviewControlSize: 90px;
-mediaviewIconSize: size(60px, 56px);
+mediaviewIconSize: size(46px, 54px);
 
 mediaviewWaitHide: 2000;
 mediaviewHideDuration: 1000;
@@ -250,9 +254,9 @@ mediaviewFadeDuration: 150;
 mediaviewDeltaFromLastAction: 5px;
 mediaviewSwipeDistance: 80px;
 
-mediaviewCaptionPadding: margins(18px, 10px, 18px, 10px);
+mediaviewCaptionPadding: margins(11px, 6px, 11px, 6px);
 mediaviewCaptionMargin: size(11px, 11px);
-mediaviewCaptionRadius: 2px;
+mediaviewCaptionRadius: 6px;
 
 mediaviewGroupPadding: margins(0px, 14px, 0px, 14px);
 mediaviewGroupHeight: 80px;
@@ -317,6 +321,8 @@ mediaviewTitle: WindowTitle(defaultWindowTitle) {
 	closeIconActive: mediaviewTitleClose;
 	closeIconActiveOver: mediaviewTitleClose;
 }
+mediaviewShadowTop: icon{{ "mediaview/shadow_top", windowShadowFg }};
+mediaviewShadowBottom: icon{{ "mediaview/shadow_bottom", windowShadowFg }};
 
 themePreviewSize: size(903px, 584px);
 themePreviewBg: windowBg;
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp
index 880cc2b9d..a4d7c8875 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.cpp
@@ -29,6 +29,31 @@ constexpr auto kGroupThumbsOffset = kCaptionOffset + 4;
 constexpr auto kControlsOffset = kGroupThumbsOffset + 4;
 constexpr auto kControlValues = 2 * 4 + 4 * 4;
 
+[[nodiscard]] ShaderPart FragmentApplyControlsFade() {
+	return {
+		.header = R"(
+uniform sampler2D f_texture;
+uniform vec4 shadowTopRect;
+uniform vec2 shadowBottomAndOpacity;
+)",
+		.body = R"(
+	float topHeight = shadowTopRect.w;
+	float bottomHeight = shadowBottomAndOpacity.x;
+	float opacity = shadowBottomAndOpacity.y;
+	float viewportHeight = shadowTopRect.y + topHeight;
+	float fullHeight = topHeight + bottomHeight;
+	float topY = min(
+		(viewportHeight - gl_FragCoord.y) / fullHeight,
+		topHeight / fullHeight);
+	float topX = (gl_FragCoord.x - shadowTopRect.x) / shadowTopRect.z;
+	vec4 fadeTop = texture2D(f_texture, vec2(topX, topY)) * opacity;
+	float bottomY = max(fullHeight - gl_FragCoord.y, topHeight) / fullHeight;
+	vec4 fadeBottom = texture2D(f_texture, vec2(0.5, bottomY)) * opacity;
+	result.rgb = result.rgb * (1. - fadeTop.a) * (1. - fadeBottom.a);
+)",
+	};
+}
+
 [[nodiscard]] ShaderPart FragmentPlaceOnTransparentBackground() {
 	return {
 		.header = R"(
@@ -77,6 +102,7 @@ OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
 : _owner(owner) {
 	style::PaletteChanged(
 	) | rpl::start_with_next([=] {
+		_controlsFadeImage.invalidate();
 		_radialImage.invalidate();
 		_documentBubbleImage.invalidate();
 		_themePreviewImage.invalidate();
@@ -118,6 +144,15 @@ void OverlayWidget::RendererGL::init(
 			FragmentSampleARGB32Texture(),
 		})).vertex;
 
+	_staticContentProgram.emplace();
+	LinkProgram(
+		&*_staticContentProgram,
+		_texturedVertexShader,
+		FragmentShader({
+			FragmentSampleARGB32Texture(),
+			FragmentApplyControlsFade()
+		}));
+
 	_withTransparencyProgram.emplace();
 	LinkProgram(
 		&*_withTransparencyProgram,
@@ -125,6 +160,7 @@ void OverlayWidget::RendererGL::init(
 		FragmentShader({
 			FragmentSampleARGB32Texture(),
 			FragmentPlaceOnTransparentBackground(),
+			FragmentApplyControlsFade()
 		}));
 
 	_yuv420Program.emplace();
@@ -133,6 +169,7 @@ void OverlayWidget::RendererGL::init(
 		_texturedVertexShader,
 		FragmentShader({
 			FragmentSampleYUV420Texture(),
+			FragmentApplyControlsFade()
 		}));
 
 	_nv12Program.emplace();
@@ -141,6 +178,7 @@ void OverlayWidget::RendererGL::init(
 		_texturedVertexShader,
 		FragmentShader({
 			FragmentSampleNV12Texture(),
+			FragmentApplyControlsFade()
 		}));
 
 	_fillProgram.emplace();
@@ -195,6 +233,7 @@ void OverlayWidget::RendererGL::paint(
 	if (_factor != factor) {
 		_factor = factor;
 		_controlsImage.invalidate();
+		_controlsFadeImage.invalidate();
 	}
 	_blendingEnabled = false;
 	_viewport = widget->size();
@@ -283,7 +322,12 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
 		}
 		_chromaNV12 = nv12;
 	}
-	if (!nv12) {
+
+	validateControlsFade();
+	if (nv12) {
+		_f->glActiveTexture(GL_TEXTURE2);
+		_controlsFadeImage.bind(*_f);
+	} else {
 		_f->glActiveTexture(GL_TEXTURE2);
 		_textures.bind(*_f, 3);
 		if (upload) {
@@ -297,6 +341,9 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
 			_chromaSize = yuv->chromaSize;
 			_f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 		}
+
+		_f->glActiveTexture(GL_TEXTURE3);
+		_controlsFadeImage.bind(*_f);
 	}
 	program->setUniformValue("y_texture", GLint(0));
 	if (nv12) {
@@ -305,6 +352,7 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
 		program->setUniformValue("u_texture", GLint(1));
 		program->setUniformValue("v_texture", GLint(2));
 	}
+	program->setUniformValue("f_texture", GLint(nv12 ? 2 : 3));
 
 	toggleBlending(false);
 	paintTransformedContent(program, geometry);
@@ -325,7 +373,7 @@ void OverlayWidget::RendererGL::paintTransformedStaticContent(
 
 	auto &program = fillTransparentBackground
 		? _withTransparencyProgram
-		: _imageProgram;
+		: _staticContentProgram;
 	program->bind();
 	if (fillTransparentBackground) {
 		program->setUniformValue(
@@ -369,7 +417,13 @@ void OverlayWidget::RendererGL::paintTransformedStaticContent(
 			_rgbaSize = image.size();
 		}
 	}
+
+	validateControlsFade();
+	_f->glActiveTexture(GL_TEXTURE1);
+	_controlsFadeImage.bind(*_f);
+
 	program->setUniformValue("s_texture", GLint(0));
+	program->setUniformValue("f_texture", GLint(1));
 
 	toggleBlending(semiTransparent && !fillTransparentBackground);
 	paintTransformedContent(&*program, geometry);
@@ -412,6 +466,15 @@ void OverlayWidget::RendererGL::paintTransformedContent(
 	_contentBuffer->write(0, coords, sizeof(coords));
 
 	program->setUniformValue("viewport", _uniformViewport);
+	const auto &top = st::mediaviewShadowTop.size();
+	program->setUniformValue(
+		"shadowTopRect",
+		Uniform(transformRect(
+			QRect(QPoint(_viewport.width() - top.width(), 0), top))));
+	const auto &bottom = st::mediaviewShadowBottom;
+	program->setUniformValue(
+		"shadowBottomAndOpacity",
+		QVector2D(bottom.height() * _factor, geometry.controlsOpacity));
 
 	FillTexturedRectangle(*_f, &*program);
 }
@@ -607,6 +670,36 @@ void OverlayWidget::RendererGL::invalidateControls() {
 	ranges::fill(_controlsTextures, QRect());
 }
 
+void OverlayWidget::RendererGL::validateControlsFade() {
+	if (!_controlsFadeImage.image().isNull()) {
+		return;
+	}
+	const auto width = st::mediaviewShadowTop.width();
+	const auto bottomTop = st::mediaviewShadowTop.height();
+	const auto height = bottomTop + st::mediaviewShadowBottom.height();
+
+	auto image = QImage(
+		QSize(width, height) * _factor,
+		QImage::Format_ARGB32_Premultiplied);
+	image.fill(Qt::transparent);
+	image.setDevicePixelRatio(_factor);
+
+	auto p = QPainter(&image);
+	st::mediaviewShadowTop.paint(p, 0, 0, width);
+	st::mediaviewShadowBottom.fill(
+		p,
+		QRect(0, bottomTop, width, st::mediaviewShadowBottom.height()));
+	p.end();
+
+	_controlsFadeImage.setImage(std::move(image));
+	_shadowTopTexture = QRect(
+		QPoint(),
+		QSize(width, st::mediaviewShadowTop.height()) * _factor);
+	_shadowBottomTexture = QRect(
+		QPoint(0, bottomTop) * _factor,
+		QSize(width, st::mediaviewShadowBottom.height()) * _factor);
+}
+
 void OverlayWidget::RendererGL::paintFooter(QRect outer, float64 opacity) {
 	paintUsingRaster(_footerImage, outer, [&](Painter &&p) {
 		const auto newOuter = QRect(QPoint(), outer.size());
@@ -699,25 +792,25 @@ void OverlayWidget::RendererGL::paintRoundedCorners(int radius) {
 
 	_f->glDisableVertexAttribArray(position);
 }
-
-void OverlayWidget::RendererGL::invalidate() {
-	_trackFrameIndex = -1;
-	_streamedIndex = -1;
-	const auto images = {
-		&_radialImage,
-		&_documentBubbleImage,
-		&_themePreviewImage,
-		&_saveMsgImage,
-		&_footerImage,
-		&_captionImage,
-		&_groupThumbsImage,
-		&_controlsImage,
-	};
-	for (const auto image : images) {
-		image->setImage(QImage());
-	}
-	invalidateControls();
-}
+//
+//void OverlayWidget::RendererGL::invalidate() {
+//	_trackFrameIndex = -1;
+//	_streamedIndex = -1;
+//	const auto images = {
+//		&_radialImage,
+//		&_documentBubbleImage,
+//		&_themePreviewImage,
+//		&_saveMsgImage,
+//		&_footerImage,
+//		&_captionImage,
+//		&_groupThumbsImage,
+//		&_controlsImage,
+//	};
+//	for (const auto image : images) {
+//		image->setImage(QImage());
+//	}
+//	invalidateControls();
+//}
 
 void OverlayWidget::RendererGL::paintUsingRaster(
 		Ui::GL::Image &image,
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h
index 668a75113..2cf5994a2 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_opengl.h
@@ -70,7 +70,7 @@ private:
 	void paintGroupThumbs(QRect outer, float64 opacity) override;
 	void paintRoundedCorners(int radius) override;
 
-	void invalidate();
+	//void invalidate();
 
 	void paintUsingRaster(
 		Ui::GL::Image &image,
@@ -79,6 +79,7 @@ private:
 		int bufferOffset,
 		bool transparent = false);
 
+	void validateControlsFade();
 	void validateControls();
 	void invalidateControls();
 	void toggleBlending(bool enabled);
@@ -105,6 +106,7 @@ private:
 
 	std::optional<QOpenGLBuffer> _contentBuffer;
 	std::optional<QOpenGLShaderProgram> _imageProgram;
+	std::optional<QOpenGLShaderProgram> _staticContentProgram;
 	QOpenGLShader *_texturedVertexShader = nullptr;
 	std::optional<QOpenGLShaderProgram> _withTransparencyProgram;
 	std::optional<QOpenGLShaderProgram> _yuv420Program;
@@ -121,6 +123,7 @@ private:
 	int _streamedIndex = 0;
 	bool _chromaNV12 = false;
 
+	Ui::GL::Image _controlsFadeImage;
 	Ui::GL::Image _radialImage;
 	Ui::GL::Image _documentBubbleImage;
 	Ui::GL::Image _themePreviewImage;
@@ -134,6 +137,9 @@ private:
 	[[nodiscard]] static Control ControlMeta(OverState control);
 	std::array<QRect, kControlsCount> _controlsTextures;
 
+	QRect _shadowTopTexture;
+	QRect _shadowBottomTexture;
+
 	bool _blendingEnabled = false;
 
 	rpl::lifetime _lifetime;
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp
index 3755be032..60707c97a 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_raster.cpp
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 
 #include "ui/painter.h"
 #include "media/view/media_view_pip.h"
+#include "styles/style_media_view.h"
 
 namespace Media::View {
 
@@ -73,6 +74,7 @@ void OverlayWidget::RendererSW::paintTransformedVideoFrame(
 		return;
 	}
 	paintTransformedImage(_owner->videoFrame(), rect, rotation);
+	paintControlsFade(rect, geometry.controlsOpacity);
 }
 
 void OverlayWidget::RendererSW::paintTransformedStaticContent(
@@ -89,10 +91,34 @@ void OverlayWidget::RendererSW::paintTransformedStaticContent(
 	if (fillTransparentBackground) {
 		_p->fillRect(rect, _transparentBrush);
 	}
-	if (image.isNull()) {
-		return;
+	if (!image.isNull()) {
+		paintTransformedImage(image, rect, rotation);
 	}
-	paintTransformedImage(image, rect, rotation);
+	paintControlsFade(rect, geometry.controlsOpacity);
+}
+
+void OverlayWidget::RendererSW::paintControlsFade(
+		QRect geometry,
+		float64 opacity) {
+	_p->setOpacity(opacity);
+	_p->setClipRect(geometry);
+	const auto width = _owner->width();
+	const auto &top = st::mediaviewShadowTop;
+	const auto topShadow = QRect(
+		QPoint(width - top.width(), 0),
+		top.size());
+	if (topShadow.intersected(geometry).intersects(_clipOuter)) {
+		top.paint(*_p, topShadow.topLeft(), width);
+	}
+	const auto &bottom = st::mediaviewShadowBottom;
+	const auto bottomShadow = QRect(
+		QPoint(0, _owner->height() - bottom.height()),
+		QSize(width, bottom.height()));
+	if (bottomShadow.intersected(geometry).intersects(_clipOuter)) {
+		bottom.fill(*_p, bottomShadow);
+	}
+	_p->setClipping(false);
+	_p->setOpacity(1.);
 }
 
 void OverlayWidget::RendererSW::paintTransformedImage(
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_raster.h b/Telegram/SourceFiles/media/view/media_view_overlay_raster.h
index 7e91f660b..25d3d3248 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_raster.h
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_raster.h
@@ -32,6 +32,7 @@ private:
 		const QImage &image,
 		QRect rect,
 		int rotation);
+	void paintControlsFade(QRect geometry, float64 opacity);
 	void paintRadialLoading(
 		QRect inner,
 		bool radial,
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
index aa4f64971..b5d3498d4 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
@@ -790,6 +790,11 @@ void OverlayWidget::updateControlsGeometry() {
 	_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
 	_photoRadialRect = QRect(QPoint((width() - st::radialSize.width()) / 2, (height() - st::radialSize.height()) / 2), st::radialSize);
 
+	const auto bottom = st::mediaviewShadowBottom.height();
+	const auto top = st::mediaviewShadowTop.size();
+	_bottomShadowRect = QRect(0, height() - bottom, width(), bottom);
+	_topShadowRect = QRect(QPoint(width() - top.width(), 0), top);
+
 	updateControls();
 	resizeContentByScreenSize();
 	update();
@@ -1367,6 +1372,7 @@ bool OverlayWidget::updateControlsAnimation(crl::time now) {
 		_controlsOpacity.update(dt, anim::linear);
 	}
 	_helper->setControlsOpacity(_controlsOpacity.current());
+	const auto content = finalContentRect();
 	const auto toUpdate = QRegion()
 		+ (_over == OverLeftNav ? _leftNav : _leftNavIcon)
 		+ (_over == OverRightNav ? _rightNav : _rightNavIcon)
@@ -1377,7 +1383,9 @@ bool OverlayWidget::updateControlsAnimation(crl::time now) {
 		+ _nameNav
 		+ _dateNav
 		+ _captionRect.marginsAdded(st::mediaviewCaptionPadding)
-		+ _groupThumbsRect;
+		+ _groupThumbsRect
+		+ content.intersected(_bottomShadowRect)
+		+ content.intersected(_topShadowRect);
 	update(toUpdate);
 	return (dt < 1);
 }
@@ -1407,6 +1415,7 @@ QRect OverlayWidget::finalContentRect() const {
 }
 
 OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
+	const auto controlsOpacity = _controlsOpacity.current();
 	const auto toRotation = qreal(finalContentRotation());
 	const auto toRectRotated = QRectF(finalContentRect());
 	const auto toRectCenter = toRectRotated.center();
@@ -1418,7 +1427,7 @@ OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
 			toRectRotated.width())
 		: toRectRotated;
 	if (!_geometryAnimation.animating()) {
-		return { toRect, toRotation };
+		return { toRect, toRotation, controlsOpacity };
 	}
 	const auto fromRect = _oldGeometry.rect;
 	const auto fromRotation = _oldGeometry.rotation;
@@ -1441,7 +1450,7 @@ OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
 		fromRect.width() + (toRect.width() - fromRect.width()) * progress,
 		fromRect.height() + (toRect.height() - fromRect.height()) * progress
 	);
-	return { useRect, useRotation };
+	return { useRect, useRotation, controlsOpacity };
 }
 
 void OverlayWidget::updateContentRect() {
@@ -4152,6 +4161,7 @@ void OverlayWidget::paintControls(
 		const QRect &outer;
 		const QRect &inner;
 		const style::icon &icon;
+		bool nonbright = false;
 	};
 	const QRect kEmpty;
 	// When adding / removing controls please update RendererGL.
@@ -4161,13 +4171,15 @@ void OverlayWidget::paintControls(
 			_leftNavVisible,
 			_leftNav,
 			_leftNavIcon,
-			st::mediaviewLeft },
+			st::mediaviewLeft,
+			true },
 		{
 			OverRightNav,
 			_rightNavVisible,
 			_rightNav,
 			_rightNavIcon,
-			st::mediaviewRight },
+			st::mediaviewRight,
+			true },
 		{
 			OverSave,
 			_saveVisible,
@@ -4193,9 +4205,9 @@ void OverlayWidget::paintControls(
 		if (!control.visible) {
 			continue;
 		}
-		const auto bg = overLevel(control.state);
-		const auto icon = bg * st::mediaviewIconOverOpacity
-			+ (1 - bg) * st::mediaviewIconOpacity;
+		const auto progress = overLevel(control.state);
+		const auto bg = progress;
+		const auto icon = controlOpacity(progress, control.nonbright);
 		renderer->paintControl(
 			control.state,
 			control.outer,
@@ -4206,6 +4218,15 @@ void OverlayWidget::paintControls(
 	}
 }
 
+float64 OverlayWidget::controlOpacity(
+		float64 progress,
+		bool nonbright) const {
+	const auto normal = _windowed
+		? kNormalIconOpacity
+		: kMaximizedIconOpacity;
+	return progress + (1. - progress) * normal;
+}
+
 void OverlayWidget::paintFooterContent(
 		Painter &p,
 		QRect outer,
@@ -4221,7 +4242,7 @@ void OverlayWidget::paintFooterContent(
 	const auto date = _dateNav.translated(shift);
 	if (header.intersects(clip)) {
 		auto o = _headerHasLink ? overLevel(OverHeader) : 0;
-		p.setOpacity((o * st::mediaviewIconOverOpacity + (1 - o) * st::mediaviewIconOpacity) * opacity);
+		p.setOpacity(controlOpacity(o) * opacity);
 		p.drawText(header.left(), header.top() + st::mediaviewThickFont->ascent, _headerText);
 
 		if (o > 0) {
@@ -4235,7 +4256,7 @@ void OverlayWidget::paintFooterContent(
 	// name
 	if (_nameNav.isValid() && name.intersects(clip)) {
 		float64 o = _from ? overLevel(OverName) : 0.;
-		p.setOpacity((o * st::mediaviewIconOverOpacity + (1 - o) * st::mediaviewIconOpacity) * opacity);
+		p.setOpacity(controlOpacity(o) * opacity);
 		_fromNameLabel.drawElided(p, name.left(), name.top(), name.width());
 
 		if (o > 0) {
@@ -4247,7 +4268,7 @@ void OverlayWidget::paintFooterContent(
 	// date
 	if (date.intersects(clip)) {
 		float64 o = overLevel(OverDate);
-		p.setOpacity((o * st::mediaviewIconOverOpacity + (1 - o) * st::mediaviewIconOpacity) * opacity);
+		p.setOpacity(controlOpacity(o) * opacity);
 		p.drawText(date.left(), date.top() + st::mediaviewFont->ascent, _dateText);
 
 		if (o > 0) {
@@ -4323,6 +4344,7 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
 		} else if (_fullScreenVideo) {
 			if (key == Qt::Key_Escape) {
 				playbackToggleFullScreen();
+			} else if (ctrl) {
 			} else if (key == Qt::Key_0) {
 				activateControls();
 				restartAtSeekPosition(0);
@@ -4337,7 +4359,6 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
 				activateControls();
 				seekRelativeTime(kSeekTimeMs);
 			}
-
 			return;
 		}
 	}
@@ -4379,8 +4400,6 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
 			zoomIn();
 		} else if (key == Qt::Key_Minus || key == Qt::Key_Underscore) {
 			zoomOut();
-		} else if (key == Qt::Key_0) {
-			zoomReset();
 		} else if (key == Qt::Key_I) {
 			update();
 		}
@@ -5090,10 +5109,13 @@ bool OverlayWidget::filterApplicationEvent(
 		not_null<QEvent*> e) {
 	const auto type = e->type();
 	if (type == QEvent::ShortcutOverride) {
-		const auto keyEvent = static_cast<QKeyEvent*>(e.get());
-		const auto ctrl = keyEvent->modifiers().testFlag(Qt::ControlModifier);
-		if (keyEvent->key() == Qt::Key_F && ctrl && _streamed) {
+		const auto event = static_cast<QKeyEvent*>(e.get());
+		const auto key = event->key();
+		const auto ctrl = event->modifiers().testFlag(Qt::ControlModifier);
+		if (key == Qt::Key_F && ctrl && _streamed) {
 			playbackToggleFullScreen();
+		} else if (key == Qt::Key_0 && ctrl) {
+			zoomReset();
 		}
 		return true;
 	} else if (type == QEvent::MouseMove
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
index becfa9053..2411089f9 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
@@ -154,6 +154,7 @@ private:
 	struct ContentGeometry {
 		QRectF rect;
 		qreal rotation = 0.;
+		qreal controlsOpacity = 0.;
 	};
 	struct StartStreaming {
 		StartStreaming() : continueStreaming(false), startTime(0) {
@@ -417,6 +418,9 @@ private:
 		QRect clip,
 		float64 opacity);
 
+	[[nodiscard]] float64 controlOpacity(
+		float64 progress,
+		bool nonbright = false) const;
 	[[nodiscard]] bool isSaveMsgShown() const;
 
 	void updateOverRect(OverState state);
@@ -552,6 +556,9 @@ private:
 	object_ptr<Ui::LinkButton> _docSaveAs;
 	object_ptr<Ui::LinkButton> _docCancel;
 
+	QRect _bottomShadowRect;
+	QRect _topShadowRect;
+
 	QRect _photoRadialRect;
 	Ui::RadialAnimation _radial;