From 537607201076cb20bef3ec0b6edb52d5c145a900 Mon Sep 17 00:00:00 2001 From: Vivek Date: Sun, 12 Jul 2026 23:55:06 +0530 Subject: [PATCH] chore: add on-device ?diag= A/B harness for Android soft-nav CSS (#936) The Android-Chrome soft-nav CSS loss (#936) does not reproduce in headless Blink across every emulated path, so confirming the cause needs a real device. This adds a query-param A/B harness to the marketing site, the same on-device method used for the iOS oklch repaint bug (#610). Loading any page with ?diag= bakes a small head script (persisted across client-router soft navs) that applies a repaint/recalc nudge to the swapped DOM after each nav, plus an on-screen badge showing the active mode and path. Modes: control (baseline, no nudge), reflow, repaint, recolor, nudge (display toggle). Whitelisted, so only a known literal reaches the inline script; entirely absent without the param, so production is byte-unchanged. References #936 (diagnostic step; the framework fix follows once a mode is confirmed to restore styling on-device). --- website/app/layout.ts | 58 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/website/app/layout.ts b/website/app/layout.ts index 3c91fb4b1..6c918f1e9 100644 --- a/website/app/layout.ts +++ b/website/app/layout.ts @@ -60,8 +60,19 @@ export function generateMetadata(ctx: { url: string }) { const navLink = 'text-fg-muted no-underline font-medium text-sm px-[11px] py-2 rounded-lg transition-colors duration-[140ms] hover:text-fg hover:bg-bg-subtle'; const panelLink = 'text-fg-muted no-underline font-medium text-sm px-3 py-[10px] rounded-[9px] hover:text-fg hover:bg-bg-subtle'; -export default function RootLayout({ children }: { children: unknown }) { +export default function RootLayout({ children, url }: { children: unknown; url?: string | URL }) { const nonce = cspNonce(); + // #936 on-device A/B diagnostic. Inert unless the ENTRY page is loaded with + // ?diag=. The mode is baked into a head script that persists across + // client-router soft navs (add-only head merge keeps it), so loading + // /?diag=nudge once governs the whole session. Whitelisted so the value that + // reaches the inline script is always a known literal. + const DIAG_MODES = new Set(['control', 'reflow', 'repaint', 'recolor', 'nudge']); + let diagMode = ''; + try { + const raw = new URL(String(url ?? ''), 'http://x').searchParams.get('diag') || ''; + if (DIAG_MODES.has(raw)) diagMode = raw; + } catch { /* no url in this context */ } return html` @@ -141,6 +152,51 @@ export default function RootLayout({ children }: { children: unknown }) { }); + + ${diagMode ? html`` : ''} +