diff --git a/tradein-mvp/frontend/src/app/v2/page.tsx b/tradein-mvp/frontend/src/app/v2/page.tsx
index 706ed177..09fc21fc 100644
--- a/tradein-mvp/frontend/src/app/v2/page.tsx
+++ b/tradein-mvp/frontend/src/app/v2/page.tsx
@@ -617,6 +617,19 @@ export default function TradeInV2Page() {
rightContent = ;
}
+ // Polite SR announcement reflecting the estimate lifecycle. Same precedence as
+ // middleContent: loading → error → insufficient → ready → silent.
+ let statusMessage = "";
+ if (loading) {
+ statusMessage = "Идёт расчёт оценки…";
+ } else if (restoreError) {
+ statusMessage = "Ошибка загрузки отчёта";
+ } else if (estimate && insufficient) {
+ statusMessage = "Недостаточно данных для оценки";
+ } else if (estimate && !insufficient) {
+ statusMessage = "Оценка готова";
+ }
+
return (
+ {/* Polite, visually-hidden status announcer for SR users. */}
+
+ {statusMessage}
+
+
{/* OUTER HUD FRAME */}
@@ -159,21 +159,26 @@ export function ObjectSummary({
{/* Per-section totals (clickable) */}
{data.summary.rows.map((row, i) => (
-
onNavigate(row.nav)}
+ aria-label={`${row.label} — подробнее`}
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
padding: "9px 6px",
+ cursor: "pointer",
+ borderRadius: 5,
+ width: "100%",
+ fontFamily: "inherit",
+ textAlign: "left",
borderBottom:
i < data.summary.rows.length - 1
? `1px dotted ${tokens.lineGradient}`
: undefined,
- cursor: "pointer",
- borderRadius: 5,
}}
>
›
-
+
))}
diff --git a/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx b/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx
index 227d691c..179d5686 100644
--- a/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx
+++ b/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx
@@ -273,9 +273,11 @@ export default function ResultPanel({
/>
))}
-
onNavigate(card.nav)}
+ aria-label={`Подробнее — ${card.title.join(" ")}`}
style={{
display: "flex",
alignItems: "center",
@@ -285,18 +287,24 @@ export default function ResultPanel({
letterSpacing: 0.3,
color: accent,
whiteSpace: "nowrap",
+ background: "none",
+ border: "none",
+ padding: 0,
+ margin: 0,
+ fontFamily: "inherit",
}}
>
Подробнее →
-
+
) : (
<>
-
onNavigate(card.nav)}
+ aria-label={`Подробнее — ${card.title.join(" ")}`}
style={{
- marginTop: 16,
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
@@ -305,10 +313,17 @@ export default function ResultPanel({
fontSize: 9,
letterSpacing: 0.3,
color: accent,
+ width: "100%",
+ background: "none",
+ border: "none",
+ padding: 0,
+ margin: 0,
+ marginTop: 16,
+ fontFamily: "inherit",
}}
>
Подробнее →
-
+
-
onNavigate(3)}
+ aria-label="Подробнее — цена и срок продажи"
style={{
display: "flex",
alignItems: "center",
@@ -646,11 +663,16 @@ export default function ResultPanel({
fontSize: 9,
letterSpacing: 0.3,
color: accent,
+ background: "none",
+ border: "none",
+ padding: 0,
+ margin: 0,
marginTop: 2,
+ fontFamily: "inherit",
}}
>
Подробнее →
-
+
{/* right range — deals */}
@@ -756,9 +778,11 @@ export default function ResultPanel({
>
ИСТОЧНИКИ ДАННЫХ
- onNavigate(i)}
+ aria-current={active === i ? "page" : undefined}
className={`tnav-tab${active === i ? " tnav-tab--active" : ""}`}
- style={{ position: "relative", whiteSpace: "nowrap" }}
+ style={{
+ position: "relative",
+ whiteSpace: "nowrap",
+ background: "none",
+ border: "none",
+ padding: 0,
+ margin: 0,
+ // NB: family/size/letterSpacing inherit for chrome reset, but do
+ // NOT set `font`/`color` shorthand — the .tnav-tab(--active)/:hover
+ // CSS must keep driving tab colour + weight.
+ fontFamily: "inherit",
+ fontSize: "inherit",
+ letterSpacing: "inherit",
+ cursor: "pointer",
+ }}
>
{label}
)}
-
+
))}
{/* User menu */}
-
-
{
+ if (e.key === "Escape") setUserOpen(false);
+ }}
+ >
+
+
{userOpen && (
-
{
setUserOpen(false);
onLogout?.();
}}
className="tnav-logout"
- style={{ ...menuItemStyle, color: tokens.danger }}
+ style={{
+ ...menuItemStyle,
+ color: tokens.danger,
+ width: "100%",
+ fontFamily: "inherit",
+ textAlign: "left",
+ }}
>
Выйти
-
+
)}