- Add `ContinueWatching` (systemSmall) and `Upcoming` (systemSmall) SwiftUI widgets via `expo-widgets`, registered in `app.json` under the `group.com.jakejarvis.sofa` app group
- Add `widget-images` local Expo module with a Swift `WidgetImagesModule` that downloads and resizes remote poster images into the shared app group container for use by widgets; also copies bundled assets (sofa icon fallback)
- Add `src/lib/widgets.ts` to fetch dashboard data, cache poster images, and write a JSON timeline to the shared container via `expo-widgets`
- Add `ContinueWatching` and `Upcoming` SwiftUI widget views in `src/widgets/`
- Add `useWidgetRefresh` hook that refreshes widgets on foreground (throttled to once per minute) and on session ready
- Debounce widget refresh in `invalidateTitleQueries` so rapid mutations (e.g. marking multiple episodes watched) batch into a single refresh
- Expose `titles.upcoming` from the dashboard procedure and add `upcomingTitles` field to the dashboard schema
- Bump iOS deployment target to 16.2 (required by WidgetKit timeline APIs)
- Add `Link.Menu` with contextual actions to `PosterCard` (add to watchlist, mark completed, remove), `HeroBanner` ("Add to Watchlist"), and `ContinueWatchingCard` ("Mark as Completed", "Remove from Library") — all invalidate the relevant `titles` and `dashboard` query keys on success
- Remove the `failedKey`/`resetError` error-state pattern from `usePosterActions` and strip the now-unused `failedKey` and `onQuickAddFailed` props from every call site (`HorizontalPosterRow`, `person/[id].tsx`, `PosterCard`)
- Restructure `ContinueWatchingCard` JSX so `GestureDetector` wraps the outer `Animated.View` rather than sitting inside `Link`, fixing gesture/preview layering
- Simplify single-argument plugin entries in `app.json` from `["plugin-name"]` to `"plugin-name"`
- Replace `Alert` with `toast` for sign-in/register errors and add a `getFormErrors` utility to extract the first Zod validation message and field set
- Display the configured server host inline on the login screen and hide the navigation header in the auth layout (`headerShown: false`, `navigationBarHidden: true`)
- Delete `AuthStackHeader` and `DetailStackHeader`; introduce `ModalStackHeader` for screens that are pushed as modals
- Remove unused `StatusBadge` component and delete unused shadcn web components (`calendar`, `drawer`)
- Bump all Expo 55 SDK packages to their latest patch versions and add `expo-web-browser` plugin to `app.json` + `@react-navigation/native` as an explicit dependency
Replace the three `@expo-google-fonts` npm dependencies (dm-sans, dm-serif-display, geist-mono) with locally vendored TTF files under `assets/fonts/`. Update `app.json` font paths accordingly and consolidate the four separate DM Sans Android font-family entries into a single `"DM Sans"` family with multiple weight definitions. Rename font family identifiers throughout components and `global.css` to match the simplified names (`DM Sans`, `DM Serif Display`, `Geist Mono`).