Ctrl K
ComunidadGuías…

docs/mobile-responsive-audit.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Responsive parity audit

Status: in progress. Goal: responsive feature parity across existing views, excluding chart and dashboard editing. Use representative before/after screenshots and a primary interaction check per view family; route availability alone is insufficient. Following user feedback on September 15, prioritize broad coverage and clear usability blockers over exhaustive control-by-control verification.

Desktop → mobile replacements, layout changes, breakpoints and exceptions are tracked in [the responsive pattern map](mobile-responsive-patterns.md). Update that map whenever the audit introduces another recurring transformation.

Evidence directory: `/Users/joaoviana/.codex/visualizations/2026/09/14/01a0a012-54e2-7651-a7f9-2c4435316b21/mobile-audit/`.

Test sizes: phone 390×844 (also 360px boundary), tablet 768×1024, desktop 1440×1000. Test resize/rotation without reloading, keyboard focus, nested overlays, local table scrolling, and preserved URL state.

## September 15 follow-up: phone scope and controls

This supersedes earlier phone authoring/drill/restore checks below: chart and dashboard creation/editing, including Explore from here, are intentionally unavailable on detected phones, independent of viewport width. Narrow desktop windows and tablets retain authoring. Responsive presentation remains width-driven: search narrows before secondary action labels condense below 1088px, the project label hides below 896px, search becomes an icon below 600px, and the Menu drawer begins strictly below 512px. Homepage curation controls show at the top of a compact layout and hide after scrolling. Inactive or unconfigured Autopilot stays on the homepage instead of reserving a navbar cell.

Dashboard chart tile actions use a single vertical-ellipsis menu below 512px; desktop retains the hover pill.

- Replaced boxed navigation tiles with grouped list rows. The compact header preserves the logo, search and Ask AI controls, with an icon-only overflow trigger; project switching and account controls live in the Drawer. Its controls use 44px interaction targets. Dashboard and saved-chart headers switch below 640px and share explicit title/actions/metadata grid slots with 16px horizontal padding. Long titles wrap; favorites move into the menu. Actions have plain icons and invisible 44px touch areas. Dashboard refresh uses one menu on phones; manual and timed refresh pass behavioral tests.
- Nested navigation menus now expand inline inside the phone Drawer. AI agent conversations move the agent selector and Settings into the thread Drawer below 768px, remove the local header divider, and limit starter suggestions to two below 512px.
- Fixed the settings drawer's overflowing flex body. At 390×844 the option list scrolled from 0 to 1657px; Data ops and Review requests became reachable while search/close stayed visible. Reused the bounded body for both shared Page drawers and AI settings.
- Dashboard filters stay inline through 640px, then use a drawer matching the compact dashboard header. A temporary numeric filter was added, retained across 768/1024/390px resizes, then reset. Add/Reset remain one row; long filter labels can wrap. Saved-chart filter forms now stack field/operator/value inputs on phones; parameter labels wrap and keep one-column phone fields.
- Browser screenshots: `lightdash-header-plain-after.png`, `lightdash-nav-drawer-after.png`, `lightdash-settings-sidebar-after.png`, `lightdash-settings-sidebar-bottom.png`, `lightdash-filter-form-after.png`, `lightdash-filter-chip-after.png`, `lightdash-tablet-768-after.png`, `lightdash-tablet-1024-after.png`, `lightdash-saved-chart-after.png` in the evidence directory. The subsequent alignment pass supersedes the first header captures: `lightdash-dashboard-header-grid.png`, `lightdash-saved-chart-header-grid.png`, `lightdash-chart-header-aligned.png` and `lightdash-chart-tablet-aligned.png`. The saved-chart check used a chart without parameters; populated parameter controls were covered in the earlier audit, not re-verified in this follow-up.
- Validation: 46 focused tests across route boundaries, refresh, chart editor/history, filter rules, parameters and canvas state preservation. Frontend typecheck and changed-file lint pass. Device-based editor blocking and narrow-desktop availability are regression-tested.

## Approved header direction B

The user selected B for both dashboard and saved-chart headers. This supersedes the earlier title/actions two-column pass. Titles now use the full width; metadata is below; a separated row contains three equally sized labeled actions. Dashboard: Refresh / Share / More. Saved chart: Share / Favorite / More. Existing permissions still control availability. Details move into More and remain reachable for read-only viewers.

- Verified phone header crops at 390px and 320px, and the unchanged saved-chart desktop toolbar at 768px. Evidence: `lightdash-dashboard-b.png`, `lightdash-dashboard-b-320.png`, `lightdash-chart-b.png`, `lightdash-chart-b-320.png`, `lightdash-chart-b-tablet.png`.
- Opened Details on both pages and Auto-refresh from the dashboard menu. Direct refresh and scheduled refresh pass tests, including switching between phone and desktop controls without resetting the schedule.
- 33 focused tests pass across refresh, chart-editor header and authoring boundaries; frontend typecheck and changed-file lint pass.

## Coverage ledger

| View family                                           | Before                                                                                                  | After                                                                                     | Behavior verified                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Login, registration, recovery, invitations            | Login/register baseline; recovery/invite intermediate captures                                          | Legacy signup, new recovery, reset and invitation states captured                         | Phone sign-in, one-click invitation, reset success, consumed reset rejection and login with changed password verified on a disposable account. Password guidance stays inline on phones. Email-sending submissions unexercised.                                                                                                                                                                                                                                                         |
| Project selection and onboarding                      | Intermediate source/form/error/menu captures                                                            | Source picker, PostgreSQL, created project, dbt CLI/manual and expert invitation captured | Keyboard warehouse selection, PostgreSQL Test & save, error recovery, project switching, Homebrew tab, manual navigation and invite Cancel verified. External warehouse/SSO, dbt deploy and expert email submission unexercised.                                                                                                                                                                                                                                                        |
| Home, pinned content, favorites                       | Home family baseline; footer overlap captured during audit                                              | Home and populated pinned/favorites states captured                                       | Favorite appears on home; pinned link opens the temporary space. Favorite persists across reload after re-adding. Footer follows the full content height and is reachable by scrolling. Favorite persistence across moves and published/custom home editing remain pending.                                                                                                                                                                                                             |
| Spaces, nested space, shared with me                  | Captured                                                                                                | Capture sweep underway                                                                    | Content-view selection changes URL; optional Access column available. Created temporary parent/child; renamed child, moved it to project root, then deleted through confirmation. Space menu opens by keyboard. Sharing and access-list layouts inspected; no invitations sent.                                                                                                                                                                                                         |
| Dashboard list, chart list, search                    | Captured; search baseline after shared-route change                                                     | Search and preview captured                                                               | Search preview → Open navigates correctly; list action coverage pending.                                                                                                                                                                                                                                                                                                                                                                                                                |
| Dashboard, tabs, filters, parameters                  | Captured                                                                                                | Filter sheet/value and desktop resize captured                                            | Added First name=Michael; URL and value survive phone → desktop → phone. Tabs switch line/bar charts and preserve selected URL on resize. Required Status selection loads the chart; Reset reopens guidance. Parameter status and custom duration values work; values survive phone → desktop → phone; controls disappear on unrelated tabs and return with their values. Clear duration resets to default.                                                                             |
| Chart view, data, drill actions                       | Captured                                                                                                | Phone/tablet/desktop captured                                                             | Results show data. Underlying data returns one row; Status drill opens a new exploration showing returned/count 1. XLSX download verified (header + one row, 48 columns).                                                                                                                                                                                                                                                                                                               |
| Sharing, exports, schedules, comments                 | Schedule creation baseline captured after route consolidation                                           | Creation, format section, schedule list captured                                          | Draft name survives section selection; preview expands; cancel returns to list. Draft form state preserved; paused local fixture covers populated detail/edit/history/delete and was removed. No delivery ran. Underlying-data export fits 360px and scrolls in landscape; XLSX download verified. Comment controls, populated thread/replies, unsent draft resize, resolve/reopen/delete and Go to tile verified. Sharing mutations, mentions and other export formats remain pending. |
| Chart/dashboard history and comparison                | Captured                                                                                                | Phone history and version selector captured                                               | Chart current version renders; dashboard selector opens. Local QA fixture adds history versions; comparison opens on phone. Expanded comparison table scrolls locally; restore succeeds on the local fixture and restores its original middle chart.                                                                                                                                                                                                                                    |
| Metrics catalog, metric detail, canvas                | Catalog/metric modal and saved-tree sidebar/editor baselines; intermediate picker/dialog states         | Detail, dates, picker, columns and populated tree states captured                         | Custom dates, presets, segmentation and filtering verified. Details/SQL and column controls work by keyboard. Saved-tree add/drivers/connect/cleanup/save/delete, expanded view and breakpoint preservation verified; first viewer period change fixed. Comparison modes, keyboard selection/clear and category CRUD verified. Owner filtering/details verified. Icon writes/skin-tone checks remain pending.                                                                           |
| Tables, SQL runner, query history                     | Captured; history was unavailable before route consolidation                                            | Capture sweep underway                                                                    | History row opens details; next query updates results. SQL query select 1 as mobile_check returns 1. Phone Re-run returns HTTP 200 and produces a new ready query with one result row; the selected historical detail stays open. Remaining table workflows pending.                                                                                                                                                                                                                    |
| Data apps, gallery, previews                          | Original app route redirected; creation captured after shared-route changes                             | Creation, builder, preview, viewer, info, fullscreen captured                             | Build/Preview switch and element picking work; draft and iframe survive switching/resizing. Template selection and draft preserved at 360px. Native fullscreen exits through visible button. Gallery, sharing, screenshot attachment, version restore and external connections pending.                                                                                                                                                                                                 |
| Ask AI: selection, conversation, artifacts, memory    | Existing greeting captured after route changes                                                          | New conversation and threads drawer captured                                              | QA prompt completes; response and suggestions fit. Threads drawer opens/closes. Provider returned text without a chart; artifact and memory workflows remain pending.                                                                                                                                                                                                                                                                                                                   |
| Ask AI administration and evaluations                 | Pending                                                                                                 | Pending                                                                                   | Pending                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| Review requests, autopilot, activity, deleted content | Captured                                                                                                | Capture sweep underway                                                                    | Activity fixed-width grid replaced; review layout constrained. Detailed workflows pending.                                                                                                                                                                                                                                                                                                                                                                                              |
| Learn and help                                        | Pending                                                                                                 | Pending                                                                                   | Pending                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| Personal, organization, project settings              | Original settings family blocked on mobile; new subsection baselines captured after shared-route change | 15 subsection captures; project/users fixes captured                                      | Project filters and user search fit; service accounts route gated. Settings mutation workflows pending.                                                                                                                                                                                                                                                                                                                                                                                 |
| Embedded dashboard/chart/app/catalog/AI               | Narrow-host overflow reproduced                                                                         | Dashboard, Spanish, narrow-host captured                                                  | Dashboard reflows at host width 360px without window resize; filter collapse and Spanish UI work. Other embed surfaces pending.                                                                                                                                                                                                                                                                                                                                                         |

Feature-gated views require supported local fixtures/configuration. Record unavailable external integrations explicitly; never label unexercised behavior verified.

## Findings and implementation decisions

| Before                                                                                                                                | Intended after                                                                                   | Why / evidence                                                                                                         |
| ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Mobile navigation exposes only Home, Spaces, Dashboards, Charts, Logout in the seeded session.                                        | Responsive access to the same authorized desktop destinations and actions.                       | `before/navigation-phone.png`; desktop Home exposes search, settings, metrics, notifications, AI, and more.            |
| Metrics, shared content, apps, gallery, query history, deleted content, learn, reviews, and autopilot URLs redirect to Home at 390px. | The requested view renders at the same URL.                                                      | Corresponding `before/*-phone.json` and screenshots record the final URL.                                              |
| Settings, tables, SQL runner, registration, and chart history show the unsupported-mobile page.                                       | Existing views adapt to available width.                                                         | `before/settings-phone.png`, `tables-phone.png`, `sql-phone.png`, `register-phone.png`, `chart-history-phone.png`.     |
| Saved chart opens an untitled minimal chart with no normal header/actions.                                                            | Full viewer identity and authorized actions, with usable chart/data controls.                    | `before/chart-phone.png`; reproduction: open `/projects/jaffle-shop/saved/how-many-orders-we-have-over-time` at 390px. |
| Dashboard opens minimal tiles without the normal dashboard header. A tutorial tile occupies nearly the full first viewport.           | Shared dashboard viewer with compact header, filters, tabs, and content-appropriate tile sizing. | `before/dashboard-phone.png`; reproduction: open `/projects/jaffle-shop/dashboards/jaffle-dashboard/view` at 390px.    |
| Dashboard history URL opens the minimal dashboard rather than history.                                                                | Same history view and URL as desktop.                                                            | `before/dashboard-history-phone.json`.                                                                                 |

Source inspection also identifies global 900/600px page minimum widths and load-time-only route selection. Runtime overflow and resize checks will verify their replacements.

## Verification log

- 2026-09-14: isolated instance bootstrap started in tmux `mobile_e48b:bootstrap`. Assigned frontend 3070, API 8150, PostgreSQL 6132. Dependencies were absent initially.
- API and scheduler use an isolated PM2 daemon (`PM2_HOME=/tmp/lightdash-e48b-pm2`) because the shared daemon references a removed worktree dependency. Frontend/watchers remain in the assigned global PM2 namespace. API health returned 200; demo login succeeded.

## Implementation checkpoint (2026-09-14)

- One route tree now serves all viewport sizes; removed unused MobileRoutes, duplicate mobile pages/navbar, and load-time IS_MOBILE. Ask AI uses the shared navbar. Homepage availability follows its feature/settings gate on phones too.
- Mantine Drawer handles navigation, Page sidebars and dashboard filters; shared MantineModal becomes full-screen for phone forms. Navbar stacking no longer hides modal controls.
- Search becomes full-screen with explicit close, readable results and touch-accessible per-result previews. Desktop retains split results/preview.
- Resource lists retain configurable metadata columns. Content-view/type controls become labeled selects on phones. Query history uses a compact source selector and wrapping filters.
- Usage analytics now fits its grid to available width; review requests have a constrained content wrapper.
- Dashboard tile projection is deterministic, independent of saved desktop coordinates; four pure tests pass.
- Filter configuration widths now fit the viewport. Apply supports pointer and keyboard activation, with a 10-test behavior suite passing.
- Latest frontend typecheck and lint passed; shared modal (5 tests), visualization portal/Page (6), and auth routes (2) passed. Remaining UI coverage is not inferred from those checks.

### Local QA configuration

Enabled `LIGHTDASH_PREVIEW_FEATURE_FLAGS_ENABLED=true` in this instance's ignored `.env.development.local`, then restarted only its API/scheduler through tmux. This uses the supported shared resolver and exposes Query history, reviews and Learn for QA. Original value is stored at `/tmp/lightdash-mobile-qa-flag-original.json`; restore it after the audit. No product flag definitions/defaults changed. Earlier screenshots used the instance's normal feature flags; feature availability therefore differs in later QA captures.

### Known remaining gaps

- External integrations and AI provider-backed operations are not yet verified; existing slug/UUID API errors appear on some seeded commercial routes.
- Full settings subsections, auth recovery/invitation UI, chart/drill actions, dashboard tabs/required filters/parameters, sharing/schedules/comments, history comparisons, embeds, exports, and real-device touch checks still need targeted coverage.
- Screenshot sweeps are evidence collection, not a pass verdict. `progress/` images include intermediate defects; `after/` images still require the coverage ledger's corresponding behavior checks.

### Additional layout verification

- Scheduled delivery creation uses a full-screen Mantine Modal below `lg`, a section Select and expandable preview. List/detail mode stacks below `lg`. Existing desktop three-column creation remains. Populated paused delivery detail is now captured and inspected at phone/desktop widths.
- Settings capture sweep covers users/groups, attributes, warehouse credentials, projects, access tokens, integrations, roles, AI general/agents/threads/evals/memories, deliveries and appearance. Baseline settings routes were unsupported on phones; subsection screenshots taken after route consolidation are marked intermediate, not original before.
- Project filter toolbar wraps; user search no longer has a 350px mobile minimum. AI default model control stacks under its description.
- Tablet QA found header CSS used an inclusive 768px breakpoint while Mantine switched at 768px, causing header actions to overlap filters. Shared PageHeader, viewer actions and filter sheet now consistently switch below `md` (992px). Recaptured 768px dashboard confirms separation.
- Desktop dashboard and review table screenshots inspected; original dashboard grid and header retained. Empty review state remains centered.
- Evidence gallery indexes 64 view/state entries; missing before/after captures stay explicitly marked. Route and document-width checks supplement visual inspection, not substitute for it.

- Current verification: frontend typecheck clean, lint clean (3,201 files), 28 focused tests pass across grid, Page/portal, modal, scheduler form, filter Apply, and auth routes. Removed obsolete MobileRoutes Vite warmup entry; auth rerun passes without the missing-file warning.

- Metric exploration baseline reproduced: fixed 800px modal body puts visualization offscreen. Below `lg`, modal is full-screen with the visualization above scrollable controls. Phone screenshot captured; Next changes the URL from total to average population. Detailed filter/date/segment behavior and desktop comparison remain pending. New embed-reachable navigation labels use the common UI-string registry with Spanish/Georgian examples.

- User authorized substantially smaller mobile charts. Saved/SQL dashboard charts now project to 60% of saved height, bounded to 3–6 rows (~185–380px); Loom uses 4 rows. Desktop sizes and data-app sizing remain unchanged. Grid bounds/nonmutation checks pass; horizontal bar chart capture inspected: labels and legend remain readable. Remaining chart types still need inspection.
- Phone SQL query `select 1 as mobile_check` returns one row with value `1`. SQL title wraps, Monaco suggestions are constrained below `md`. Initial automation input concatenated text; corrected using focused editor + Meta+A + native keyboard input, then verified successful execution. No chart saved.
- Latest targeted layout tests: 18 pass (grid, SQL create header, Page visualization portal).

### Embed container audit

- SDK test app runs in tmux `mobile_e48b:sdk-preview`, port 3072, aliasing current SDK source. The existing token generator produced local 24-hour dashboard, metrics and AI tokens. Its output is kept in `/tmp/lightdash-mobile-embed-token-output.txt`; ignored SDK `.env.local` was configured, original contents backed up at `/tmp/lightdash-mobile-sdk-env-backup`. Restore after QA. No content was saved.
- At desktop viewport width, changing only the host embed to 360px left grid children spanning 1174px. The existing react-grid-layout WidthProvider listens only to window resize. Replaced it across dashboard, embed and minimal/export viewers with a shared Mantine `useElementSize` wrapper. Hidden tabs retain the last nonzero width. Same host now has grid client/scroll width 344px, and tiles visibly stack.
- Embed filter controls wrap using intrinsic flex sizing, preserving existing public CSS contract classes. This covers narrow containers on otherwise wide host pages. Collapse/translation checks underway.

- Embed regression check passes: container resize reflows real grid tiles with no window event; zero-width hidden tabs retain sizing. Embed Hide → Show filters works at a 360px host width; switching Spanish updates filter UI and dashboard markdown. Narrow-container screenshots captured. Main AI workspace uses dynamic viewport height, and thread menus remain visible on non-hover devices.

- Kept compact chart-height projection out of the minimal export renderer: exports retain saved chart heights, while app/embed viewers use mobile sizing. The minimal renderer only adopts container width observation. Desktop export-layout screenshots underway.

- Desktop minimal/export and standard dashboard screenshots inspected after width-observer replacement; saved grid sizes preserved. Current frontend typecheck clean.

### Drill, export, required-filter and parameter checks

- Shared modal header actions occupy their own row on phones, with 44px action/close targets. Fixed mobile content width on both Mantine inner/content elements; small dialogs previously stayed ~300px wide despite fullscreen mode. Mobile offsets override desktop caller offsets; required-filter dialog retains its 420px width and 200px top offset at 1440×1000.
- ExportResults popovers use viewport-bounded width and height, with scrolling and non-shrinking children. At 360×740 all normal options fit; at 844×390 the Download button is reachable by scrolling and retains its 32px height. Removed an explicit foreground shade that made the underlying-data export label invisible.
- Downloaded `/tmp/lightdash-mobile-underlying.xlsx` through the UI; valid XLSX contains a header and one data row with 48 cells. Underlying-data and drill screenshots inspected. Drill Status → Open in new tab yields returned/count 1.
- QA-only browser guard suppresses agent-browser's synthetic Unidentified keydown events, which otherwise dismiss menus/popovers after CLI actions. Real keys remain enabled; no product event workaround added. Clicking partly offscreen table cells also requires explicit scroll-into-view in this CLI.
- Created local fixtures recorded in `/tmp/lightdash-mobile-created-fixtures.json`: tab/history dashboard `4c0db4e7-5fda-430e-9e21-07910357652c`, required-filter dashboard `bb155e14-58d1-4bf7-87a9-0c19d313c979`, parameter chart `22ac885b-f820-4dcc-a7c3-a195a1f36262`. Existing content unchanged. Remove these fixtures after QA.
- Required-filter Status=completed removes the guide and loads the chart; Reset all filters restores the guide. Selected value appears in URL. New fixture state screenshots follow the original route-level baselines; no pre-change fixture screenshots are implied.
- Previously reported disabled filter/parameter pills were an accessibility artifact from disabled drag wrappers (`role=button`, `aria-disabled=true`, tabindex=0). Controls still responded to pointer input. Disabled wrappers now omit drag attributes/listeners, preserving child control semantics and keyboard focus. Regression test fails before and passes after; enabled drag target remains keyboard-focusable.
- Parameter Subscription Status=Cancelled and custom Minimum Duration=13 both update the viewer. Clear controls now have an embed-localizable label. Ten modal/export tests and two drag-wrapper tests pass; parameter checks and final lint/typecheck continue.

- Parameter state survives phone → desktop → phone and switching away/back. Unrelated tabs hide those controls without clearing the URL values. Clear duration resets to default 0. Parameter tests pass (3); frontend typecheck and lint pass (3,204 files). Evidence gallery now indexes 80 states; navigation images load and view/viewport controls render.
- History comparison table and restore dialog captured. Restoring the oldest QA dashboard version navigates back to the dashboard; API confirms the original middle chart reference. Existing charts were not changed.
- Paused delivery fixture `385a25de-4a48-4dff-abb3-36df536df043` revealed an existing API behavior: creation ignored enabled=false and returned enabled=true. Immediately paused via PATCH /schedulers/{uuid}/enabled; confirmed false. Weekly Monday 09:00 schedule was already past at creation; runs API returns totalResults=0. Pause deletes queued jobs; same-owner changes skip owner notification. No Send action used. Delete this fixture after layout QA. Do not create another scheduler assuming the creation enabled flag is honored.

- Paused schedule detail, populated edit form, empty run history, and deletion dialog fit on phones; desktop detail layout inspected. Cancel from edit works by keyboard (the dev-only React Query launcher covers the pointer target). Added accessible names for enable switch/delete control. Deleted the local fixture via its confirmation UI; API list returns zero schedules. No delivery was sent.
- Removed both QA dashboards and the parameter chart after their checks; original referenced charts remain accessible. Fixture payloads/IDs and cleanup flags remain in `/tmp/lightdash-mobile-created-fixtures.json` for reproducibility. These were local test resources, not seeded/user content.

- Final batch verification: 15 focused tests pass (5 modal, 5 export, 2 drag-wrapper, 3 parameter); frontend typecheck clean, lint clean on 3,204 files, changed-file formatting and diff whitespace checks clean. Gallery indexes 85 view/state entries. Full parity remains in progress; unchecked ledger rows are not certified by these results.

### Data-app builder and AI conversation checks

- Data-app builder uses a Mantine SegmentedControl below `md` to switch Build/Preview. Both panes remain mounted; CSS controls visibility and gives the selected pane full width. Desktop keeps its resizable split and collapse state. Browser checks preserve an unsent draft, selected element reference, and the exact iframe element across phone → desktop → tablet → phone.
- Element-picker activation opens Preview; selecting the placeholder heading returns to Build with its reference. Version preview actions also select Preview. Screenshot attachment reveals the preview and waits for layout before capture; actual screenshot attachment remains unverified because this fixture did not report screenshot availability.
- Creation template cards use two columns on phones. At 360×740, selected Dashboard template and draft remain; Send is visible at y=655–695, and document width equals 360. Desktop retains the card fan.
- Shared app header wraps with natural mobile height and bounded info popover. App builder/viewer use dynamic viewport height. Fullscreen previously hid every app control; added a 44px Exit fullscreen action and verified native fullscreen entry/exit.
- Uploaded the unchanged sandbox starter source as temporary app `363e6f0c-b839-44e3-84b4-8fd07a7c31af`; build completed. This exercises the real preview iframe, but its placeholder content does not certify query-heavy apps. Deleted the app through the API afterward; subsequent GET/DELETE reports not found.
- Existing AI greeting conversation fits. Created temporary thread `43b7385d-f06d-4f08-9e6b-7fce51c724bf` with Qwen3.5 9B; its request completed with text and suggestions but no chart. Captured phone/desktop response. Threads Drawer now has a labeled 44px close control; open/close verified.
- Preview flags also enable the organization’s thread-deletion-disable flag, so the temporary AI thread’s deletion API returned 403. Removed only that local QA thread in a transaction matching the model’s cleanup order (approval/context/memory/thread). Original greeting thread remains. No pending QA app/thread fixture remains.
- Twenty app tests pass (element picker, header actions, iframe preview); frontend typecheck and lint clean. Template-picker checks and final evidence indexing recorded below. New builder states lack original pre-routing baselines; gallery keeps those missing states explicit.

- Final app batch: 26 tests pass including template selection; formatting and diff whitespace checks clean. Evidence gallery indexes 92 view/state entries. AI artifacts, gallery detail, app screenshot capture and remaining ledger workflows are still open.

### Home, spaces and access dialogs

- Reproduced home footer overlapping cards on phones. Compact Page used `flex: 1` with a zero basis and minimum height, shrinking the main below its overflowing content. Normal scrolling pages now use an automatic flex basis; full-height editor/viewer layouts retain their existing scroll behavior. Main measured 1351px, footer starts after its bottom with the expected 20px margin. Footer content now fits its container instead of imposing a 900px minimum. Phone and desktop bottom-of-page captures inspected.
- SpaceBrowserMenu wrapped an ActionIcon in another ActionIcon and attached Mantine Menu.Target to a div. It now targets the caller’s labeled button directly; Add also targets its button directly. Mobile actions are 44px. Keyboard Tab/Enter opens the menu and Share invokes its callback in the regression test.
- Sharing’s access-mode selector clipped its Restricted access option at 390px even though document/dialog scroll widths appeared correct. The description and segmented control now stack below `sm`; options have 44px targets. Shared-user rows can wrap. Phone inherited-access and populated Who has access list inspected; desktop modal retains its horizontal control layout. No sharing invitations or comments were sent.
- Space destination rows and expand buttons now have 44px mobile targets; removed the 200px per-node minimum so deeply indented labels can shrink. Expand/Collapse controls have names/state. Project-root destination can be selected using Tab/Enter; new behavioral tests cover root selection and expansion.
- Local fixtures: parent `3727f0c9-4c57-472c-8494-ea51411419c3`, child `2fbcdc4e-1ab5-4f49-80ff-c81602003789`. Created both via UI, renamed child, moved it to project root (API confirms parentSpaceUuid=null), favorited/pinned it and verified home rendering/navigation. Child deleted through typed-name UI confirmation; empty parent deleted via API. Child lookup returns 404; favorites list returns zero.
- Favorite was absent after the move/intervening interactions; re-adding persisted across reload. The cause has not been isolated, so persistence across moves is not certified. Pin survived move/rename. Remaining published-home, sharing mutations and comments need coverage.
- Eleven focused tests passed for space menu, sharing input and Page/visualization integration. Eight tests passed for destination tree and menu, including three new keyboard/accessibility regressions; these counts overlap. Evidence gallery indexes 99 states.

- Final checks for this batch: frontend typecheck clean; lint clean on 3,205 files; changed-file formatting and diff whitespace checks clean.

### Tile actions and comments

- Tile toolbar stays mounted, reveals on keyboard focus, and uses visible 44px controls on compact/touch layouts. It wraps below long titles when needed. Desktop keeps the floating toolbar; no per-tile viewport hook or duplicate mobile tree. Existing chart-height projection remains unchanged.
- Chart/data-app filter, parameter, time-zone and execution information use Mantine Popover with viewport bounds. Filter and execution panels opened by keyboard/pointer on the phone. Added accessible tile/AI/info labels through the embed UI registry and Spanish/Georgian demo bundles. Parameter/time-zone and data-app information still need dedicated populated visual checks.
- Tile comments are bounded to viewport width/height, allow placement changes during resize, and use fixed positioning with two-axis shifting. A sticky 44px close control remains reachable while the panel scrolls. Reply/composer buttons are 44px on compact/touch screens; comment action buttons reveal on touch and keyboard focus.
- Created two local database-only comment fixtures (parent/reply), with no mentions or notification events. Read/reply expansion, unsent draft preservation at 360×740 → 844×390 → 1440×1000, resolve/reopen, and deletion exercised. No comment was submitted or message sent. Deleting the parent through the UI removed both fixture rows; SQL count verified zero. IDs and cleanup recorded in `/tmp/lightdash-mobile-created-fixtures.json`.
- Dashboard comments drawer fills a phone and stays 420px on desktop. Go to tile closes the compact drawer so the destination is visible; desktop retains the panel. Tab section selectors use native keyboard buttons. Found an existing legacy-dashboard bug: untabbed tiles were labeled removed. Grouping now distinguishes existing untabbed tiles from removed ones; pure regression test covers their separation.
- New populated comment states were introduced during this checkpoint, so they have after-only fixture evidence. The original dashboard baseline remains the reference for hidden tile actions. Browser checks were repeated after reload when HMR retained stale popover placement.
- Current checks: 16 focused frontend tests pass across comments and grid behavior; frontend typecheck/lint clean (3,206 files), 7 UI-registry tests pass, Spanish/Georgian bundles cover all 227 registry keys, and changed-file formatting is clean. Gallery now indexes 108 view/state entries. Broader parity remains in progress; unexercised ledger rows remain pending.

### Auth and onboarding

- Compact auth forms use dynamic viewport height, safe-area padding, 44px controls and 16px input text. Names stack on phones; autofill and email input types are explicit. Password requirements stay inline on compact screens, so the helper no longer covers the submit button; desktop keeps its focus popover and the input stays mounted across breakpoints.
- Warehouse and dbt choice cards are native buttons. Compact source/dbt/expert pages reduce padding; warehouse inputs and expert form actions have 44px targets. Job errors have a named 44px close control. Project switcher dropdown width/height are bounded to the viewport; project labels shrink while current badges remain visible.
- Disposable local user covered one-click invitation, expected no-project access state, password reset success, consumed-link rejection, and login using the changed password. Legacy signup captured without submitting its email-generating activation. Recovery email validation checked without sending. Expert form Cancel returns to source selection; no invitation sent.
- PostgreSQL setup exercised Test & save against this instance's database. Explicit port 6132 and SSL disabled succeeded; failure state captured before correcting the connection. Temporary project was renamed Mobile QA source, selected/switched through the phone menu, and deleted through the API. Homebrew tab changes its command; manual dbt option navigates to integrations. No dbt deployment or external connection was run.
- Temporary user `c2f02d7c-d26c-4452-a4f6-804450e748fe` and project `0318cdd1-c7e5-4959-9b85-990535e982ab` removed. The temporary database default for new-onboarding was restored to its original absent state; SQL verifies all three counts zero. Existing preview environment configuration remains for the broader audit.
- 22 focused tests pass across auth routes, password guidance, source picker, dbt onboarding and expert invitation. Frontend typecheck and lint pass. Signup, form, project-menu and reset screenshots inspected. Shared code-block copy contrast/touch sizing fixed and verified below.

- Shared CodeBlock now uses CodeHighlight.Control's built-in tooltip. The outer Tooltip previously overwrote the control classes, leaving its icon white on the light code background. Phone/touch controls use a separate row with 44px targets; desktop retains its 28px overlay controls. Browser confirms both copy and expand styling; Copy changes to Copied. SQL code and local horizontal scrolling remain available.
- Query-history Re-run returns HTTP 200; readback confirms a new ready query `6acba207-7b8c-4583-a833-a467a4d76d71` with one result row. Existing selected history item remains open by current design. No chart/content saved.
- Six CodeBlock/AI SQL modal tests pass, bringing this checkpoint to 28 focused tests. Latest frontend typecheck passes; full lint passed before the final CodeBlock change and its targeted lint/format checks pass afterward. Diff whitespace check clean. Evidence gallery indexes 129 view/state entries; missing baselines and remaining workflows stay explicit.

### Metric exploration dates and filters

- Reproduced 605px custom date popover on a 390px phone, with calendar/actions clipped. Compact screens now use a single range button opening presets and one calendar. Desktop retains its preset strip and two calendars. Shared controlled range state survives switching between layouts.
- Mantine Popover uses fixed positioning and shifts on both axes, with viewport-bounded width/height. Presets wrap into two columns; calendar and footer stack. Calendar day/picker controls and Apply/Cancel have 44px touch targets. Sticky footer keeps Apply visible while a landscape calendar scrolls. Date and granularity controls receive registry-backed accessible names; Spanish/Georgian cover all 230 keys.
- Explorer navigation/close/actions and filter inputs now have 44px compact targets. The date toolbar wraps instead of clipping presets or granularity. Browser checks cover January–February monthly selection, September 3–10 daily selection, preset Apply/Cancel, and phone → desktop → phone preservation. At 360×740 the daily panel is 336px wide within x=12–348 and y=159–728; at 844×390 it fits y=12–378 and Apply remains visible.
- Browser segmentation and Browser=Chrome filtering apply through real controls. Changing back to Monthly/12M renders populated revenue data with both selections retained. Out-of-range dates show the existing empty-data state. No chart or metric metadata was saved; no fixtures were added.
- 14 focused frontend tests pass: existing date-range, metric visualization and comparison behavior plus a new compact date-button regression covering pending preset changes, Cancel and Apply. Seven UI-registry tests pass. Frontend typecheck, targeted lint, formatting and diff whitespace checks pass. Updated phone/desktop/landscape screenshots inspected.
- Next catalog work remains concrete: MetricDetailPopover is hover-only, icon and view-switch controls lack accessible names, emoji picker uses fixed 350px positioning, and saved-tree/canvas workflows are unverified. Comparison controls and tablet/boundary coverage also remain open; this checkpoint does not certify those surfaces.

### Metric details, icons and columns

- Metric detail panels now use controlled Mantine Popover and native button targets, replacing hover-only activation. Enter opens details; Space toggles compiled SQL; Escape and the labeled close control dismiss. Explore closes the panel before opening the metric explorer. SQL selection survived the checked phone-to-landscape resize. Dropdowns stay within viewport bounds and scroll on short screens.
- Replaced the catalog icon picker's hand-positioned portal, window-coordinate math and table scroll lock with Mantine Popover. Search for rocket returned the expected emoji; Escape and Close work without changing metadata. Phone emoji/category targets are 44px and search text is 16px. Category sprites retain their 20px art inside larger targets. Skin-tone controls still use the library's small targets and need separate touch review.
- Very short 844×247 viewport exposed a collapsed emoji area. The picker keeps its internal 300px height; the outer panel scrolls with a sticky close header. At scrollTop=130, Close remains y=21–65 and the first emoji is y=87–131. Phone 360×740 and desktop 1440×1000 captures inspected. Picker-open state across resizing is not certified: some transitions close it, and browser actions can precede layout settlement.
- List/Canvas radio controls now have accessible names. Column visibility and reorder controls are labeled; compact rows/actions are 44px and the dropdown is bounded with two-axis shifting. Keyboard toggling Description removes/restores the table column. Original configuration restored; Save for everyone was not used. Phone dropdown contains all actions; landscape scroll behavior remains available.
- Five focused frontend tests pass, including a new keyboard/SQL/Escape/Explore regression using real Redux and a seeded query cache. Frontend typecheck, targeted lint and formatting pass; seven common UI-string tests pass. Spanish and Georgian bundles cover all 235 registry keys. No metric metadata was mutated and no fixture was created.
- Saved-tree canvas has two nested desktop split panels (saved trees, then metric choices alongside the canvas), fixed/no-wrap headers and small actions. This source audit identifies the next layout work; canvas editing/viewing, catalog comparisons/metadata mutations, and remaining full-parity ledger workflows are still pending.

- Follow-up isolated the unexpected picker closures: an unused inline `displayColumnDefOptions` object rebuilt ContentTable's cell renderers on parent rerenders. Removed that no-op configuration (row actions are disabled). Browser confirms the same trigger and picker DOM nodes, plus the rocket search, survive 844×390 → 360×740 → 1440×1000 → 844×390. This supersedes the resize uncertainty above. The final landscape search panel fits x=12–378/y=12–378.
- Six existing ContentTable hook tests and the new detail test pass together; latest frontend typecheck and targeted MetricsTable lint/format pass. Canvas selection works via native radio keyboard focus and Space. Saved-tree phone baseline captured before its layout changes.

### Saved metrics trees: sidebars and touch editing

- Phone baseline showed nested 20% saved-tree/metric panels, a clipped date bar and tiny New control. Both sidebars now share CanvasSidebar: desktop keeps resizable panels; compact layouts use Mantine Drawer with named 44px close controls. The canvas remains a stable sibling. Saved tree rows are native buttons, and keyboard Enter selects a tree and closes its drawer.
- Metric chooser adds search across loaded metric labels/tables, preserving its query when switching between sidebar and drawer. Add closes the drawer to reveal the inserted node. Existing Load more remains available. Compact chooser actions/input and canvas period options are 44px; date ranges wrap. Headers wrap and the tree-name input has an accessible name.
- Added React Flow zoom/fit controls and Remove selected, using the existing deletion path. Tap-style clicks connect source/target handles; handles have larger hit areas in compact/touch layouts. They scale with graph zoom, so extremely zoomed-out connection targets still require zooming in. Graph controls moved to a footer after the populated phone screenshot showed them covering a value.
- Disposable tree `a705986e-25a3-4fc6-9278-12ea9e9d4c8d` covered new name, metric search/add, save, direct reload, Edit, adding a second node, click-to-connect, edge selection/removal, node selection/removal and save. API confirms generation 2, one expected product_events revenue node, zero edges and lock=null. Current year to date renders US$9,778.93. Deleted through its phone confirmation dialog; API returns zero saved trees. Cleanup recorded in `/tmp/lightdash-mobile-created-fixtures.json`.
- Browser confirms identical canvas/name DOM elements and unsaved name/node through phone → desktop → phone. Saved-tree viewing preserves the canvas and selected period through landscape/desktop resizing. A six-test suite covers sidebar-to-drawer preservation, chooser filtering/add/close, and existing graph add/driver/view-only behavior. Frontend typecheck, targeted lint and formatting pass; seven UI registry tests pass and ES/KA cover all 243 keys.
- QA browser temporarily stalled. Trace `/tmp/lightdash-mobile-canvas-profile.json` recorded 87,684 keydown events, with little rendering work. Saved the fixture first, confirmed it through the API, then restarted only the audit browser with the existing synthetic-key guard installed at page initialization. Subsequent interactions were responsive. No product event workaround was added.
- Remaining tree work: short landscape canvas space (the graph can extend above the visible viewport after scrolling to its footer), fuller keyboard handling of connections, driver/cleanup and discard confirmation checks, and tablet/breakpoint evidence. This batch does not certify those remaining interactions. Populated fixture states have after-only evidence; the original empty/editor baselines remain explicit.

- Re-captured editor phone/desktop screenshots after moving graph controls to the footer. A fresh unsaved tree exercised Cancel → Keep editing (name and node retained), then Cancel → Discard (editor and nodes removed). No second tree was saved. Final discard/delete dialog screenshots inspected. The discard check supersedes that pending item above; short-landscape space, driver/cleanup behavior, full keyboard connections and tablet/boundary coverage remain open.
- Empty-tree guidance now uses a compact 180px region instead of centering below the initial phone viewport. The mobile empty-state screenshot is paired with its pre-change sidebar baseline.

### Expanded canvas and keyboard connections — September 15

- CanvasViewport keeps its children mounted while expanding to the viewport. Mantine focus trapping/return, Escape handling and scroll restoration support keyboard navigation. Nested dialogs and open period selects consume Escape first. Short landscape fit uses a 0.1 minimum zoom; zoom controls remain outside the graph. This supersedes the short-landscape limitation above.
- Connect metrics opens searchable Mantine selects for source and target, using the existing connection handler. Self-connections are excluded; duplicate directed connections show an error and disable submission. Browser search, ArrowDown/Enter selection, Tab navigation and Enter submission produce the expected edge. A real Mantine integration test exercises the same sequence inside expanded canvas.
- Browser verified YAML driver insertion (one to three nodes/two edges), adding and connecting product_events revenue (four nodes/three edges), and cleanup of an unconnected City count (five to four nodes). Graph/name DOM identity survives 390px → 768px → 992px → 991px; desktop panels appear at 992px. Nested-dialog Escape leaves expanded view open; exiting expanded view restores body scrolling. Editing an existing tree and saving preserves expansion; creating a new tree navigates to its resource and resets expansion.
- Phone screenshots exposed 32px modal inputs/footer buttons. Shared MantineModal now gives both normal and fullscreen bodies 44px inputs with 16px text, plus 44px footer buttons, on compact/touch layouts. Connection options are also 44px. The period selector is wide enough to display its full selection. The earlier small-control screenshot is preserved under progress.
- Found a saved-tree viewer bug during populated checks: the first period change after metrics loaded updated the selector but left nodes on MONTH. The reset-counter guard skipped this later change. Removed that guard; period updates now skip only nodes already using the chosen values. Regression reproduced MONTH instead of YEAR before the fix and passes for both initial load and refetch. Fresh browser load → first year-to-date selection now renders 20 payments, 728.5 payment revenue, US$728.50 order amount and US$9,778.93 product-event revenue.
- Fixture `5483f3de-8464-4a44-9afa-bec42c856678` (`mobile-qa-focused-tree`) saved as generation 2 with four nodes, three edges and lock=null, confirmed via API. Deleted through the phone dialog; API list reports totalResults=0. No messages or invitations sent.
- Inspected final expanded phone/tablet/landscape screenshots and connection validation dialog. Gallery indexes 154 view/state entries. Populated/new states have after-only evidence; original sidebar/editor baselines and intermediate dialog capture remain explicit.
- Current checks: 11 canvas tests across five files; seven UI-registry tests; frontend typecheck; targeted lint; formatting and whitespace checks. ES/KA bundles cover all 251 UI registry keys. Broader catalog metadata/comparison, AI, apps, settings, embeds and remaining ledger workflows are still pending.
- Resume environment had no running preview or browser CLI. Started OrbStack, restored agent-browser 0.36.0 via pnpm dlx, and ran the configured local bootstrap in tmux `mobile_e48b`. A temporary pnpx-to-pnpm-dlx wrapper resolves the missing launcher command. Canonical PM2 processes now serve frontend 3070/API 8150; no isolated PM2 override is needed in the current environment. The fresh browser session did not reproduce the previous navigation/relaunch failures. Prior /tmp logs and auth state were absent after the environment restart; durable screenshots remain.

### Catalog categories and descriptions — September 15

- Category cells and selection/color controls now use native buttons. Compact/touch layouts show Add category and edit actions without hover, with 44px controls and 16px inputs. Main and nested editors use bounded fixed Mantine popovers, scrollable dropdowns, sticky close controls, and a five-column compact color grid. Saving/deleting now also clears the parent's nested-popover state so dismissal keeps working.
- Browser verified category creation, keyboard entry/color selection, rename to Mobile QA category renamed, assignment, removal, and permanent deletion of the disposable tag. API confirmed blue/name update, then zero remaining QA categories. Fixture 4af6d5a7-d1f4-440d-a66a-837944576158 is deleted. Draft name/color survive phone → landscape → desktop → phone. Mantine hides an editor while its table-cell anchor is offscreen and restores it on scrolling the cell into view. Landscape editor fits x=508.5–808.5/y=12–299; selected pills and remove controls fit on phone.
- Replaced MetricCatalogCellOverlay's manual portal coordinates, document mouse listener and scroll locks with a Mantine Popover. A named expand button opens clamped descriptions by keyboard; Markdown links remain separate from the button. Dropdown height/width are viewport-bounded, with a sticky 44px close control and Escape focus return. Removed the unused overlay component and table/ref plumbing.
- Description evidence uses an explicitly temporary browser response fixture containing long Markdown and a documentation link; no project description was written. Baseline overflowed the phone right/bottom edges. After: phone x=12–378/y=332–832; landscape x=12–492/y=12–378. Close remains visible after scrolling long content. Enter opens, Escape closes and returns focus, body overflow stays unchanged. Browser network override removed and page reloaded after checks.
- Two real-Mantine description tests pass (real Markdown renderer, simulated DOM height only), covering keyboard opening, link semantics, Escape/focus return, explicit close and empty descriptions. Frontend typecheck and targeted seven-file lint pass; seven common UI-string tests pass; ES/KA cover all 262 registry keys. Category/description screenshots inspected at phone, landscape and desktop sizes. Remaining catalog comparison/owner/icon/skin-tone workflows and broader full-parity ledger remain open.

### Metric comparison controls — September 15

- Replaced clickable comparison-card containers and unnamed radio inputs with Mantine Radio labels. Native label clicks and keyboard Space now select either mode. The metric selector has an accessible name. Compact shared catalog selects/options are 44px with 16px input text; dropdowns and helper tooltips are viewport-bounded.
- Real browser checks: product_events Unique users → Compare to another metric → search Total revenue → ArrowDown/Enter selects and renders both series. Selection survives 390px → 844×390 → 1440px → 390px. Keyboard Space selects previous year; Clear unchecks both modes. No chart was saved or edited. Payments baseline has no configured comparison candidates and correctly shows its explanatory empty state; populated product-events screenshots are separately noted as a different data state.
- Inspected phone chart and scrolled controls, landscape, desktop and previous-year captures. Comparison selection remains reachable through the modal's existing vertical scrolling. Phone helper tooltip clipping found during capture and corrected with a bounded multiline tooltip.
- Four focused tests across description/comparison files pass, including named-radio keyboard switching and the existing selected-metric regression. Frontend typecheck and targeted lint pass. ES/KA cover all 267 registry keys. Full audit still has owner/icon/skin-tone, AI/artifacts/admin, apps, settings/sharing/export and embed workflows pending.

### Shared facet filters, owner details and pattern map — September 15

- Added mobile-responsive-patterns.md and linked it from this audit and the plan. It records actual desktop → compact component replacements, same-component layout changes, exact breakpoints, exceptions and implementation links. Existing AI drawer thresholds/artifact behavior remain explicitly under audit. This map is maintained as further patterns emerge.
- Shared FilterFacet options measured 29.14px on phone. Compact/touch triggers/options/clear controls now measure 44px; search text is 16px. Dropdowns are bounded in both dimensions with a sticky heading/close control. Controlled Mantine dismissal and focus return work with keyboard. Visual Checkbox/Radio indicators replace nested input controls; one native button with aria-pressed exposes each option's state. Select-all reports mixed selection and skips disabled options.
- Two focused tests cover keyboard opening/selection, selection state, select-all, disabled options, single-selection exclusivity, explicit close, Escape/focus return and Clear. Browser owner selection filters to five metrics, updates ownerUserUuid in the URL, and survives phone → landscape → desktop. Owner filter screenshots inspected; phone options measure 44px. Clear removes the selection.
- Owner email was previously hover-only. A named native owner button now opens a bounded Mantine Popover at every width, displaying full name and selectable email with a close control. Enter opens and Escape returns focus. Phone, landscape and desktop captures inspected. No owner assignment or global column configuration was saved; showing Owner was temporary local UI state.
- Runner stalled twice during column checks, including one automatic blank-tab relaunch. Interrupted/blank capture was discarded. Read-only process check showed the audit Chrome renderer above 100% CPU; it resisted graceful shutdown, so only that audit browser/process was stopped. A fresh agent-browser session, mobile-catalog-guarded, restores the previously documented QA-only Unidentified-key guard before navigation. Real Enter/Escape checks pass; no product event workaround was introduced.
- Frontend typecheck, targeted facet/owner lint, and seven common registry tests pass. ES/KA cover all 269 keys. Facet and owner source formatting/whitespace checks are clean. No disposable category or network override remains. Remaining full-parity areas include icon/skin-tone, AI artifacts/admin, app workflows, settings/sharing/export and remaining embeds.

### Audit depth correction — September 15

- User flagged excessive time on metrics catalog/Spotlight. Stop the detailed catalog pass. Continue breadth-first across AI, apps, settings, sharing and embeds; prioritize blocked navigation, unreachable controls, clipped content and lost state. Representative screenshots and primary workflows replace exhaustive metadata/control permutations.
- Final catalog change gives compact emoji skin-tone controls a wrapping row of 44px choices and enlarges clear-search. Library keyboard tone selection and search survive 390 → 844 → 360 → 1440 → 390 resizing; chosen emoji DOM carries 1f44d-1f3fd. No icon was submitted or changed; the picker was closed when priorities changed. Save/remove permutations are deferred, not a reason to hold up broader coverage.

### Breadth pass and AI settings — September 15

- Representative phone captures of AI agents, evaluations, memories, chart-type gallery, apps and integrations fit the viewport. Gallery/apps/evaluations/memories were empty states; this does not certify populated workflows. Existing agent chat also fits. No external integration was connected.
- AI agent settings had a blocking AppShell navbar covering the phone form. Below md it now becomes an Agent settings button and left Drawer; desktop retains its sidebar. Choosing navigation closes the Drawer. Form state stays mounted. Compact gutters and sticky action-bar margins now agree, removing horizontal overflow.
- Browser verified Setup → Evals, opening/canceling Create Evaluation, and an unsaved description surviving 390 → 1440 → 390 resizing. Description restored to empty without saving. Document width equals viewport width at both sizes. Final phone setup, Evals and fullscreen evaluation-modal screenshots inspected; no agent/evaluation records changed.
- Evidence: progress/breadth-\*-phone.png; after/agent-settings-{phone,desktop}.png; after/agent-evals-phone.png; after/agent-create-eval-phone.png. Sidebar baseline is progress/breadth-agent-settings-phone.png. Replacement recorded in mobile-responsive-patterns.md. Remaining coverage follows the reduced-depth approach above.
- Frontend typecheck, targeted AI settings lint, three-file formatting and whitespace checks pass. Gallery now indexes 182 states; indexing alone does not imply every capture was visually verified.

### Current-branch desktop/mobile parity sweep — September 15

- Re-ran the merged branch against a 44-route manifest on the isolated frontend at 1440×1000 and 390×844. The authenticated matrix contains 43 desktop screenshots and the same 43 live pages resized to phone width without reload. Separate signed-out sessions add desktop/mobile login and registration. Evidence and `route-matrix.tsv`: `/Users/joaoviana/.codex/visualizations/2026/09/15/01a0a4cc-bd29-7472-9611-0ab125deb8ef/current-sweep/`.
- Every authenticated pair was visually inspected. No route produced document-level horizontal overflow. Desktop navigation, settings sidebars, dashboard grids, chart tools, tables and forms retained their existing presentation. The loaded filter-test dashboard was recaptured after its queries settled; its desktop four-column grid remains intact.
- Resizing normal dashboard and saved-chart routes desktop → phone → desktop preserved the exact pathname at every step. No standard route entered `/minimal`; the explicit minimal-dashboard route remained minimal at both widths. Route regression tests cover the same invariant. Minimal routes remain reserved for explicit minimal/screenshot/embed entry points.
- Fixed two visual defects found by the sweep. Scheduled-delivery search and facets now wrap into deliberate rows on phones. Users & groups now fits user identity, the complete role control and row actions without local scrolling; group membership stays available in the Groups tab. Fresh phone/desktop captures and an opened role menu verify the changes; desktop is visually unchanged.
- Accepted for now: dense reporting/admin tables keep local horizontal scrolling; the visible primary column and controls remain usable and the document does not overflow. Empty AI evaluation/memory, app/gallery and scheduled-delivery states do not certify populated external/provider workflows. The seeded AI error toast and feature-gated redirects are existing environment/data conditions, not responsive regressions. The multicolor bottom-left control in local captures is React Query devtools, not product UI.
- Latest checks after merging the current `origin/main`: all 573 frontend files / 4,187 tests, frontend typecheck, changed-file lint, formatting and whitespace checks pass. Primary sweep: 90 before/final desktop-mobile screenshots; 96 PNGs including targeted after/interaction recaptures.

### Three-device regression loop — September 16

- Compared this branch with the exact visual-baseline commit (`ac9eb777cc`) across the same 43 authenticated routes at 1440×1000, iPad 820×1180 and iPhone 393×852. Added signed-out login and registration at all three sizes. This produced 270 screenshots. PR pages have zero document-level horizontal overflow and zero interactive controls outside the viewport; environment/data error states match the baseline. Evidence: `/Users/joaoviana/.codex/visualizations/2026/09/16/01a0a991-d0ed-7172-95fe-68aae21e0ad5/responsive-regression-loop/`.
- Used the PR merge-base (`f4a17307d357`) as the desktop action-parity oracle. All 43 routes loaded. The baseline exposed 2,352 controls and the PR 2,574; neither had a horizontally unreachable control. The PR reduced unnamed controls from 239 to 111. A second pass opened 349 baseline and 383 PR menu triggers (2,145 and 2,242 menu items). Every baseline menu signature remained available; three scanner exceptions were manually opened and verified.
- Fixed three PR-only gaps. Project settings no longer forces the iPad document wider than the viewport; its sticky actions stack/wrap below `md`. Custom roles keeps its dense table in a local horizontal scroller, and each row action has an accessible name and remains reachable on iPhone. Restored the baseline Autopilot setup/resume action in the responsive navbar; its setup modal opens on desktop, iPad and from the iPhone navigation drawer.
- Desktop before/after pairs are visually unchanged. The highest pixel-difference pairs were inspected and differ only through live data/loading timing. iPad retains authoring routes; iPhone shows the intentional editor notice. Login and registration fit every viewport; this branch restores phone registration, which the visual baseline redirects to the unsupported-page screen.
- Focused navbar/Page tests (3), frontend typecheck, full frontend lint (3,296 files), changed-file formatting and whitespace checks pass. The locally replayed Explore E2E spec passes, including the remote CI shard's failed save/edit/update chart flow (3 passing, 9 pending).