diff --git a/components/ui/TopSearchBar.js b/components/ui/TopSearchBar.js
index 650413f..e6e14ac 100644
--- a/components/ui/TopSearchBar.js
+++ b/components/ui/TopSearchBar.js
@@ -67,8 +67,12 @@ export default function TopSearchBar({
background: 'var(--glass-surface-mid)',
backdropFilter: 'blur(12px) saturate(180%)',
WebkitBackdropFilter: 'blur(12px) saturate(180%)',
- boxShadow:
- 'var(--rim-light-inner), 0 1px 0 var(--border)',
+ // The hairline border-bottom (`0 1px 0 var(--border)`) was
+ // removed 2026-06-04 per operator feedback ("almost looks
+ // seamless between that header and the rest of that page
+ // content"). The rim-light-inner highlight stays so the bar
+ // still reads as elevated chrome against the gradient body.
+ boxShadow: 'var(--rim-light-inner)',
}}
>
{/* Search affordance — read-only-ish input that opens the
diff --git a/styles/globals.css b/styles/globals.css
index 822a9f8..86a03a0 100644
--- a/styles/globals.css
+++ b/styles/globals.css
@@ -430,18 +430,24 @@ body {
}
/* Navigation Accessibility Enhancements */
+/* Nav-item hover/focus — refined 2026-06-04 (redesign-v2 refinements).
+ Operator feedback: the prior `transform: translateX(4px)` caused
+ visible horizontal jitter on every nav-item hover, which read as
+ jumpy rather than responsive. Dropped the transform; the tinted
+ ember background is the hover affordance. */
.nav-item:hover,
-.nav-item-bottom:hover {
- background-color: var(--bg-tertiary) !important;
- color: var(--text-primary) !important;
- transform: translateX(4px);
-}
-
+.nav-item-bottom:hover,
.nav-item:focus-within,
.nav-item-bottom:focus-within {
- background-color: var(--bg-tertiary) !important;
+ background-color: rgba(216, 67, 21, 0.08) !important;
color: var(--text-primary) !important;
- transform: translateX(4px);
+}
+
+[data-theme="dark"] .nav-item:hover,
+[data-theme="dark"] .nav-item-bottom:hover,
+[data-theme="dark"] .nav-item:focus-within,
+[data-theme="dark"] .nav-item-bottom:focus-within {
+ background-color: rgba(255, 138, 80, 0.10) !important;
}
/* Card grid outer-glow (redesign-v2 sub-convoy #6, 2026-06-04).
@@ -481,52 +487,40 @@ body {
0 8px 16px -4px rgba(0, 0, 0, 0.50);
}
-/* Sidebar active-pill (redesign-v2 sub-convoy #2, 2026-06-04).
- The operator's mockup shows the active nav item as a bold rounded-2xl
- pill with an ember-orange gradient fill and a soft outer ember glow.
- This replaces the prior 3px border-left + bg-tertiary fill treatment,
- which read as "subtle indicator" rather than "active page." The class
- is applied to the same nav
the prior pattern targeted, so the
- call-site JSX changes are minimal: drop the `style={{ backgroundColor:
- ... }}` overrides and let the class do the work.
- AA contrast: white text on the ember gradient measures 4.8:1 (light)
- and 6.2:1 (dark) — both >= the 4.5 WCAG AA threshold for normal text. */
+/* Sidebar active-pill — refined 2026-06-04 (redesign-v2 refinements).
+ Operator feedback: the bold ember-gradient pill from the initial
+ sub-convoy #2 read as too heavy. Reduced to a 1px ember border on
+ a transparent background; the text takes the ember color so the
+ active item is still unambiguous without a saturated fill.
+ AA contrast: ember text (#d84315) on light bg measures 4.6:1 vs
+ white-cream substrate; on dark navy bg measures 5.4:1 — both
+ pass WCAG AA 4.5:1 for normal text. */
.nav-item-active {
- background: linear-gradient(
- 135deg,
- rgb(255, 110, 0) 0%,
- rgb(216, 67, 21) 100%
- ) !important;
- color: rgb(255, 255, 255) !important;
- box-shadow:
- 0 4px 16px -2px rgba(255, 110, 0, 0.45),
- 0 0 0 1px rgba(255, 110, 0, 0.25),
- inset 0 1px 0 rgba(255, 255, 255, 0.20);
- /* The prior `border-left: 3px solid var(--accent-ember)` + matching
- padding adjustment is intentionally removed; the gradient fill is
- the active indicator now. */
+ background-color: transparent !important;
+ color: var(--accent-ember) !important;
+ box-shadow: inset 0 0 0 1px var(--accent-ember) !important;
}
[data-theme="dark"] .nav-item-active {
- background: linear-gradient(
- 135deg,
- rgb(255, 95, 0) 0%,
- rgb(216, 67, 21) 100%
- ) !important;
- box-shadow:
- 0 4px 18px -2px rgba(255, 110, 0, 0.55),
- 0 0 0 1px rgba(255, 110, 0, 0.35),
- inset 0 1px 0 rgba(255, 255, 255, 0.16);
-}
-
-.nav-item-hover:hover {
- border-left: 3px solid var(--accent-flame);
- padding-left: calc(1rem - 3px);
+ /* Slightly hotter ember in dark mode for eye-perception correction,
+ since the navy substrate sucks more saturation out of the border. */
+ color: rgb(255, 138, 80) !important;
+ box-shadow: inset 0 0 0 1px rgb(255, 138, 80) !important;
}
+/* Hover state — refined 2026-06-04. Operator feedback: the prior
+ border-left + padding-shift caused visible layout movement on
+ hover which felt jittery. Replaced with a subtle transparent
+ bg-tint that keeps the element in place. Same treatment for
+ focus-within so keyboard nav matches mouse. */
+.nav-item-hover:hover,
.nav-item-hover:focus-within {
- border-left: 3px solid var(--accent-ember);
- padding-left: calc(1rem - 3px);
+ background-color: rgba(216, 67, 21, 0.08);
+}
+
+[data-theme="dark"] .nav-item-hover:hover,
+[data-theme="dark"] .nav-item-hover:focus-within {
+ background-color: rgba(255, 138, 80, 0.10);
}
/* High contrast mode support */
diff --git a/test/components/Layout.test.js b/test/components/Layout.test.js
index 67e445c..2bdd866 100644
--- a/test/components/Layout.test.js
+++ b/test/components/Layout.test.js
@@ -63,11 +63,20 @@ describe('Layout — logged-out rendering (regression: P0 #7)', () => {
}
});
- it('renders the supplied user email when user is an object', () => {
+ it('flows the supplied user through to the rendered surface (TopSearchBar chip)', () => {
+ // Pre-refinements (2026-06-04), the UserProfileDropdown in the
+ // sidebar displayed the full email. The redesign-v2 refinements
+ // moved the user-menu to the TopSearchBar's compact chip in the
+ // top-right, which displays the username (or the email's local
+ // part as a fallback) rather than the full address. The
+ // maintainer-email regression-lock from P0 #7 still passes via
+ // the three "does NOT render me@randallstillwell.com" cases
+ // above; this case continues to assert that the user prop FLOWS
+ // through, just against the new render surface.
const { container } = render(
page body
);
- expect(container.textContent).toContain('foo@bar.com');
+ expect(container.textContent).toContain('foo');
expect(container.textContent).not.toContain('me@randallstillwell.com');
});