| auth.spec.ts:13 | anonymous protected navigation preserves the complete destination | passed | 5.3s | Video 1 |
| auth.spec.ts:24 | signed-out users can reach /login | passed | 5.3s | Video 1 |
| auth.spec.ts:24 | signed-out users can reach /signup | passed | 5.1s | Video 1 |
| auth.spec.ts:24 | signed-out users can reach /forgot-password | passed | 5.1s | Video 1 |
| auth.spec.ts:31 | login validates after blur and becomes usable after correction | passed | 7.6s | Video 1 |
| auth.spec.ts:56 | password visibility preserves the value without submitting | passed | 7.7s | Video 1 |
| auth.spec.ts:69 | auth navigation carries the entered email and continuation | passed | 8.2s | Video 1 |
| auth.spec.ts:88 | invalid credentials show feedback and allow a successful retry | passed | 9.6s | Video 1 |
| auth.spec.ts:105 | verified login submits credentials and follows a local URL including its query | passed | 9.4s | Video 1 |
| auth.spec.ts:118 | unverified login enters verification with the continuation intact | passed | 9.0s | Video 1 |
| auth.spec.ts:130 | signed-in login navigation follows its local destination | passed | 8.0s | Video 1 |
| auth.spec.ts:143 | login refuses a absolute redirect to another origin | passed | 7.7s | Video 1 |
| auth.spec.ts:143 | login refuses a protocol-relative redirect to another origin | passed | 7.7s | Video 1 |
| auth.spec.ts:143 | login refuses a backslash redirect to another origin | passed | 10.7s | Video 1 |
| auth.spec.ts:155 | signup requires a nonblank name and a valid password | passed | 6.5s | Video 1 |
| auth.spec.ts:169 | duplicate signup stays on the form with useful feedback | passed | 6.3s | Video 1 |
| auth.spec.ts:183 | signup sends credentials and campaign attribution then enters verification | passed | 11.3s | Video 1 |
| auth.spec.ts:204 | password recovery sends email and enforces cooldown across reload | passed | 11.2s | Video 1 |
| auth.spec.ts:225 | recovery honors the remaining server cooldown | passed | 10.3s | Video 1 |
| auth.spec.ts:238 | a missing reset token cannot change a password | passed | 6.7s | Video 1 |
| auth.spec.ts:249 | reset consumes the secret URL parameter but keeps it for submission | passed | 9.3s | Video 1 |
| auth.spec.ts:272 | an expired reset offers another link with the account email | passed | 5.9s | Video 1 |
| auth.spec.ts:290 | signed-out verification returns to login with continuation | passed | 7.6s | Video 1 |
| auth.spec.ts:298 | /verify-email stale links enter the code flow and discard the dead token | passed | 8.2s | Video 1 |
| auth.spec.ts:298 | /verify stale links enter the code flow and discard the dead token | passed | 7.2s | Video 1 |
| auth.spec.ts:312 | an existing valid code is accepted without an error or duplicate delivery | passed | 5.3s | Video 1 |
| auth.spec.ts:333 | a dead verification session returns to login | passed | 7.0s | Video 1 |
| auth.spec.ts:349 | verification rejects non-digits and incomplete codes, including a deleted middle digit | passed | 6.0s | Video 1 |
| auth.spec.ts:372 | pasting a code distributes digits and arrow keys move focus | passed | 10.8s | Video 1 |
| auth.spec.ts:394 | Backspace from a cleared middle code slot clears the preceding digit | passed | 6.2s | Video 1 |
| auth.spec.ts:413 | incorrect verification clears digits and allows another attempt | passed | 5.5s | Video 1 |
| auth.spec.ts:440 | successful verification refreshes the session before following the original destination | passed | 5.2s | Video 1 |
| auth.spec.ts:459 | resend becomes available after cooldown and starts a new cooldown | passed | 4.6s | Video 1 |
| auth.spec.ts:486 | verification logout clears the session and preserves continuation | passed | 8.4s | Video 1 |
| boards.spec.ts:51 | library renders hydrated owner and shared boards without previews | passed | 5.5s | Video 1 |
| boards.spec.ts:59 | search filters boards and clearing restores the whole library | passed | 12.0s | Video 1 |
| boards.spec.ts:69 | an empty search recovers when the query is replaced | passed | 11.4s | Video 1 |
| boards.spec.ts:81 | liked filter and search intersect instead of leaking unliked boards | passed | 9.5s | Video 1 |
| boards.spec.ts:93 | library loads boards beyond the first page without duplicates | passed | 7.5s | Video 1 |
| boards.spec.ts:107 | create board navigates to the new board and survives returning to library | passed | 18.1s | Video 1 |
| boards.spec.ts:119 | rejected creation keeps library usable for a successful retry | passed | 13.8s | Video 1 |
| boards.spec.ts:130 | rename submits with Enter and persists after reload | passed | 18.2s | Video 1 |
| boards.spec.ts:144 | rename rejects a whitespace-only name and Escape preserves the original | passed | 10.4s | Video 1 |
| boards.spec.ts:164 | a rejected rename preserves the draft and permits retry | passed | 10.9s | Video 1 |
| boards.spec.ts:181 | delete requires confirmation and cancelled deletion keeps the board | passed | 7.6s | Video 1 |
| boards.spec.ts:196 | confirmed deletion removes only the selected board and persists | passed | 15.3s | Video 1 |
| boards.spec.ts:209 | failed delete keeps board and confirmation open for retry | passed | 13.3s | Video 1 |
| boards.spec.ts:223 | duplicate creates a separate board while leaving source unchanged | passed | 17.8s | Video 1 |
| boards.spec.ts:243 | editor shared boards expose unshare without owner rename or delete | passed | 17.5s | Video 1 |
| boards.spec.ts:243 | viewer shared boards expose unshare without owner rename or delete | passed | 16.0s | Video 1 |
| boards.spec.ts:261 | liking from a card stays in library and persists in liked filter | passed | 16.5s | Video 1 |
| boards.spec.ts:276 | failed like restores saved state so retry performs the same operation | passed | 9.1s | Video 1 |
| boards.spec.ts:276 | failed unlike restores saved state so retry performs the same operation | passed | 11.4s | Video 1 |
| boards.spec.ts:305 | templates tab has independent empty state and returns to the library | passed | 9.7s | Video 1 |
| boards.spec.ts:318 | mobile library search and owner actions stay reachable | passed | 9.8s | Video 1 |
| canvas.spec.ts:33 | loads existing rich text and uses the board name as the document title | passed | 16.1s | Video 1 |
| canvas.spec.ts:45 | creates one text node, saves typing, and restores it after reload | passed | 27.9s | Video 1 |
| canvas.spec.ts:76 | failed text creation removes the optimistic ghost and can be retried | passed | 27.5s | Video 1 |
| canvas.spec.ts:103 | creates sticky notes with the persisted sticky discriminator | passed | 27.0s | Video 1 |
| canvas.spec.ts:129 | Backspace inside a rich text editor does not delete the canvas node | passed | 14.5s | Video 1 |
| canvas.spec.ts:148 | delete, undo, and redo preserve backend state across reload | passed | 27.0s | Video 1 |
| canvas.spec.ts:170 | failed deletion restores the selected source instead of losing it | passed | 25.2s | Video 1 |
| canvas.spec.ts:190 | node search matches note content and Escape returns to the canvas | passed | 18.2s | Video 1 |
| canvas.spec.ts:208 | unmatched node search shows an empty result and can be corrected | passed | 14.9s | Video 1 |
| canvas.spec.ts:225 | renaming a board persists and Escape cancels a second edit | passed | 24.6s | Video 1 |
| canvas.spec.ts:264 | dragging a text node saves its position across reload | passed | 28.5s | Video 1 |
| canvas.spec.ts:285 | creating a group preserves its name and dimensions after reload | passed | 23.9s | Video 1 |
| canvas.spec.ts:313 | sharing rejects an invalid email and successful Enter submission sends one invitation | passed | 17.1s | Video 1 |
| canvas.spec.ts:337 | rejected invitations retain the email for correction and retry | passed | 15.3s | Video 1 |
| canvas.spec.ts:371 | creates one assistant node and restores it after reload | passed | 24.2s | Video 1 |
| canvas.spec.ts:391 | failed assistant creation removes its optimistic placeholder | passed | 17.5s | Video 1 |
| canvas.spec.ts:409 | unsent chat drafts survive reload without creating a conversation | passed | 24.8s | Video 1 |
| canvas.spec.ts:424 | whitespace-only prompts cannot be sent | passed | 17.9s | Video 1 |
| canvas.spec.ts:437 | Shift+Enter inserts a line break while Delete edits the prompt safely | passed | 13.3s | Video 1 |
| canvas.spec.ts:457 | sending a prompt renders the streamed assistant response and unlocks input | passed | 31.0s | Video 1 |
| navigation.spec.ts:8 | Mini map preference persists across a reload | passed | 16.8s | Video 1 |
| navigation.spec.ts:8 | Background Dots preference persists across a reload | passed | 16.2s | Video 1 |
| navigation.spec.ts:8 | Connection Animations preference persists across a reload | passed | 12.8s | Video 1 |
| navigation.spec.ts:8 | Proximity Connect preference persists across a reload | passed | 18.5s | Video 1 |
| navigation.spec.ts:22 | dark mode changes the rendered theme and persists across reload | passed | 20.1s | Video 1 |
| navigation.spec.ts:35 | direct settings tab navigation loads the matching content and allows switching | passed | 14.7s | Video 1 |
| navigation.spec.ts:51 | profile niche saves trimmed text and persists after reload | passed | 34.9s | Video 1 |
| navigation.spec.ts:65 | failed profile niche save preserves edits while account loads and can be retried | passed | 37.4s | Video 1 |
| navigation.spec.ts:108 | notification preferences persist and disabling alerts disables dependent controls | passed | 49.4s | Video 1 |
| navigation.spec.ts:148 | failed notification update rolls back the visible preference and supports retry | passed | 35.9s | Video 1 |
| navigation.spec.ts:182 | API key creation masks the key, reveals it on demand, and revokes it | passed | 36.9s | Video 1 |
| navigation.spec.ts:205 | API key regeneration replaces the persisted key | passed | 28.9s | Video 1 |
| navigation.spec.ts:236 | Saved navigation reaches an actionable empty collection | passed | 27.5s | Video 1 |
| navigation.spec.ts:250 | unsaving a source removes the saved card and persists after reload | passed | 24.1s | Video 1 |
| navigation.spec.ts:276 | failed unsave restores the source card and supports a successful retry | passed | 26.8s | Video 1 |
| navigation.spec.ts:343 | pricing tabs display plans for their billing period and hide private offers | passed | 10.1s | Video 1 |
| navigation.spec.ts:360 | existing board owner can return from pricing to the board library | passed | 13.6s | Video 1 |
| navigation.spec.ts:368 | pricing ignores invalid or private checkout-plan -1 | passed | 13.0s | Video 1 |
| navigation.spec.ts:368 | pricing ignores invalid or private checkout-plan 99 | passed | 13.4s | Video 1 |
| navigation.spec.ts:368 | pricing ignores invalid or private checkout-plan not-a-plan | passed | 9.7s | Video 1 |
| sources.spec.ts:40 | blank website submission stays disabled and makes no source request | passed | 18.8s | Video 1 |
| sources.spec.ts:59 | rejects an invalid website URL: not a website | passed | 19.0s | Video 1 |
| sources.spec.ts:59 | rejects an invalid website URL: javascript:alert(1) | passed | 17.9s | Video 1 |
| sources.spec.ts:59 | rejects an invalid website URL: ftp://example.com/private | passed | 17.4s | Video 1 |
| sources.spec.ts:77 | valid website content creates a persisted source | passed | 43.3s | Video 1 |
| sources.spec.ts:102 | detects YouTube links before import and preserves the submitted URL | passed | 18.6s | Video 1 |
| sources.spec.ts:127 | canceling an import clears its draft before reopening | passed | 20.5s | Video 1 |
| sources.spec.ts:145 | rejects executable files without submitting an upload | passed | 19.7s | Video 1 |
| sources.spec.ts:164 | uploads a CSV file with its original bytes and restores the source after reload | passed | 31.3s | Video 1 |
| sources.spec.ts:200 | dropping a text file imports editable content and persists it | passed | 32.6s | Video 1 |
| sources.spec.ts:228 | oversized dropped text files are rejected before any source creation | passed | 23.9s | Video 1 |
| sources.spec.ts:252 | viewer can read content but toolbar and keyboard cannot mutate it | passed | 37.1s | Video 1 |
| sources.spec.ts:278 | viewer cannot import files by dropping them onto a read-only board | passed | 52.5s | Video 1 |
| sources.spec.ts:307 | preview boards cannot import files through drag and drop | passed | 46.8s | Video 1 |
| sources.spec.ts:332 | preview text content is readable but cannot be edited | passed | 45.1s | Video 1 |
| sources.spec.ts:362 | missing board shows an actionable access error instead of an endless spinner | passed | 20.1s | Video 1 |