## Why Google does this

An embedded web view is controlled by the app hosting it, which means the app could read what the
user types into Google's own page. Blocking it is a security decision on Google's side, it applies to
every app regardless of framework, and it is not something your server can opt out of.

## What has to happen instead

The shell intercepts the OAuth start, opens a system browser or an in-app browser tab, and handles
the return. On iOS that is `ASWebAuthenticationSession`; on Android it is Custom Tabs. Both are
purpose-built for this and both keep the session cookie in a way a plain browser launch does not.

That code lives in the shells under `mobile/ios` and `mobile/android`.

## Magic codes do not have this problem

```bash
bin/dev
```

A six-digit code arrives by email and is typed into your own form, inside your own web view. Nothing
is embedded, nothing is blocked, and no platform rule applies. It is the same flow on web and in the
app.

This is the argument for passwordless being the primary path rather than a fallback: it is the one
that works everywhere without a native detour.

## Apple's version is different again

Sign in with Apple is iOS-only and expects the native sheet rather than a web flow. So the app can
have a native Apple button and a magic code form, with Google either handled through a browser
session or left off the app entirely. That last option is legitimate, and it is the least work.

## Both providers stay optional

`User.upsert_by_email!` in `app/models/user.rb` is the single signup chokepoint, so someone who signs
in by code on the phone and by Google on the desktop lands in the same account. Which providers you
offer on which platform is a product decision, not an architectural one.

## Check it on a device

The simulator and a real phone differ here. Test the sign-in path on hardware before you submit,
because a broken sign-in is the one bug that stops review at the first screen.
