diff --git a/tradein-mvp/frontend/src/app/v2/page.tsx b/tradein-mvp/frontend/src/app/v2/page.tsx index 28fed31f..01aeff26 100644 --- a/tradein-mvp/frontend/src/app/v2/page.tsx +++ b/tradein-mvp/frontend/src/app/v2/page.tsx @@ -448,10 +448,17 @@ export default function TradeInV2Page() { // The rest of the dashboard (ParamsPanel / ResultPanel / overlays) stays // inside the scaled artboard — smaller on phones, but no longer overflowing. const [isMobile, setIsMobile] = useState(false); + // Below this width the fixed 1536px artboard scales down to an unreadable + // ~25% and there is no responsive layout yet. Rather than ship that broken + // scaled-down HUD, render an honest "open on desktop" notice instead (see the + // early return below). Starts false so SSR + first client render match the + // desktop tree; the effect flips it post-hydration → no hydration mismatch. + const [isSmallViewport, setIsSmallViewport] = useState(false); useEffect(() => { const compute = () => { setArtboardScale(Math.min(1, window.innerWidth / 1536)); setIsMobile(window.innerWidth < 768); + setIsSmallViewport(window.innerWidth < 1024); }; compute(); window.addEventListener("resize", compute); @@ -766,6 +773,48 @@ export default function TradeInV2Page() { statusMessage = "Оценка готова"; } + // Small-viewport guard: the HUD is a fixed 1536px artboard with no responsive + // layout — under ~1024px it scales to an unreadable ~25%. Show an honest + // desktop-only notice instead of the broken scaled-down copy. Placed after all + // hooks so the early return never changes hook order. Desktop (≥1024) is + // untouched. + if (isSmallViewport) { + return ( +
+ Откройте оценку на компьютере или расширьте окно браузера до 1024 px + и шире — на узком экране интерфейс отчёта нечитаем. +
+