diff --git a/webapp-next/src/app/globals.css b/webapp-next/src/app/globals.css
index 5b67b81..91254b6 100644
--- a/webapp-next/src/app/globals.css
+++ b/webapp-next/src/app/globals.css
@@ -174,7 +174,7 @@ html::-webkit-scrollbar {
margin-right: auto;
padding: 12px;
padding-top: 0;
- padding-bottom: env(safe-area-inset-bottom, 12px);
+ padding-bottom: var(--tg-viewport-content-safe-area-inset-bottom, env(safe-area-inset-bottom, 12px));
border-radius: 12px;
}
@@ -261,9 +261,25 @@ html::-webkit-scrollbar {
}
}
+/* Android low-performance devices: minimize animations (Telegram User-Agent). */
+[data-perf="low"] *,
+[data-perf="low"] *::before,
+[data-perf="low"] *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+}
+
/* Safe area for Telegram Mini App (notch / status bar). */
.pt-safe {
- padding-top: env(safe-area-inset-top, 0);
+ padding-top: var(--tg-viewport-content-safe-area-inset-top, env(safe-area-inset-top, 0));
+}
+
+/* Content safe area: top/bottom only to avoid overlap with Telegram header/bottom bar (Bot API 8.0+).
+ Horizontal padding is left to layout classes (e.g. px-3) so indents are preserved when viewport vars are 0. */
+.content-safe {
+ padding-top: var(--tg-viewport-content-safe-area-inset-top, env(safe-area-inset-top, 0));
+ padding-bottom: var(--tg-viewport-content-safe-area-inset-bottom, env(safe-area-inset-bottom, 0));
}
/* Sticky calendar header: shadow when scrolled (useStickyScroll). */
@@ -305,7 +321,7 @@ html::-webkit-scrollbar {
body {
margin: 0;
padding: 0;
- min-height: 100vh;
+ min-height: var(--tg-viewport-stable-height, 100vh);
background: var(--bg);
color: var(--text);
font-family: system-ui, -apple-system, sans-serif;
diff --git a/webapp-next/src/app/page.tsx b/webapp-next/src/app/page.tsx
index 7691a28..bc236be 100644
--- a/webapp-next/src/app/page.tsx
+++ b/webapp-next/src/app/page.tsx
@@ -50,7 +50,7 @@ export default function Home() {
const content = accessDenied ? (