# Appearance

How Profile → Appearance colours the app Monochrome, by the current car's cover colour or Warm, where the cover colour comes from, and what stays neutral.

## What it does [#what-it-does]

Profile → Appearance (`screen-Ap-Perfil-Aparencia`) offers three themes ([ADR-0016](/docs/adr/0016-appearance-and-car-colour)):

| Theme      | testID                  | Looks                                                                                                      |
| ---------- | ----------------------- | ---------------------------------------------------------------------------------------------------------- |
| Monochrome | `appearance-monochrome` | the default: the tokens of `handoff/design/DESIGN.md`, the car photo the only colour                       |
| Car colour | `appearance-car`        | the page tinted by the current car's Cover Colour, fading to black; cards and controls translucent over it |
| Warm       | `appearance-warm`       | coffee-brown surfaces and cream text                                                                       |

The primary pill stays white and green, red and orange stay reserved for state in every theme. Under Car colour, "Transition between cars" (`appearance-transition`) cross-fades the tint over 400 ms when another car comes into focus; Reduce Motion turns the fade off whatever the switch says. "Colour on the showcase too" (`appearance-showcase`, off by default) lets the public [showcase](/docs/features/showcase) take the cars' colours.

## Which colour [#which-colour]

On a car's screens (M-Veiculo and the boards under it) the tint is that car's Cover Colour: each screen calls `useAppearanceCar(vehicleId)`, which sets the car in the appearance store on focus, so the tab bar outside the screen's tree takes it too. Elsewhere it is the first current car whose colour tints (`firstTint`), so one silver car does not keep the app grey. No colour, or a seed with chroma under 0.03 (white, silver, grey, black cars), means Monochrome. The buyer's passport preview passes `null`: the passport never shows a car colour.

`tintedTheme(seed)` in `@autofolio/tokens/themes` derives the whole palette from one seed, clamped in OKLCH (lightness 0.28–0.34 at the top of the page, chroma at most 0.12). `themes.test.ts` checks WCAG AA for every text colour and the primary pill on every surface, for each theme and 24 seeds around the hue wheel; it is the gate for any change to the palettes.

## Cover Colour [#cover-colour]

The cron tick's `coverColors` job (`vehicle-photo.jobs.ts`) reads each cover once on the server and stores `vehicle_photo.dominant_color` (hex) and `color_checked_at`, so the same job is the pipeline and the backfill. `vehicle-photo.color.ts` reads only each 8×8 JPEG block's DC coefficient (a 1/8-scale image; a Worker cannot hold a decoded 12-megapixel photo), weights the centre 60 % toward the middle, clusters with k-means and keeps the cluster with the most weight × saturation. The garage list returns it as `cover.color`; the app never decodes images for it.

shortcut: PNG, WebP and arithmetic-coded JPEG covers give no colour (Monochrome); decode them when a cover in those formats needs one.

## Where the choice lives [#where-the-choice-lives]

The device's choice is in `expo-secure-store` and read synchronously at start-up through a `useSyncExternalStore` store (`platform/theme/appearance.ts`), so the first frame has the right colours. It is also saved on the account (`account_preference.appearance`, and `showcaseColor` for the showcase switch, through `accountPreference.update`), so a new phone starts with it; once a device chooses, its own choice wins.

Components read colours only through `useAppTheme()`. `apps/mobile/src/design/theme-seam.test.ts` fails on any hex or `rgb()` literal outside `design/tokens.ts`, since such a colour would stay Monochrome under the other themes.

The signed-in web app takes the same three themes from Settings → Appearance: `applyAppearance` sets `data-theme` and the `--af-color-*` variables on `<html>`. The marketing site and the passport at `/p/:token` stay as designed.

## Dev boards [#dev-boards]

`autofolio://dev/Ap-Perfil-Aparencia` opens the screen; `Ap-Garagem-Mono`, `Ap-Garagem-Cor`, `Ap-Garagem-Quente`, `Ap-Veiculo-Mono`, `Ap-Veiculo-Cor` and `Ap-Veiculo-Quente` set the theme on the device and open M-Garagem or the seeded M3.

Deferred: share-card backgrounds in the car's colour (ADR-0016's implementation notes).

## Key files [#key-files]

- [`packages/tokens/src/themes.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/packages/tokens/src/themes.ts)
- [`packages/tokens/src/themes.test.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/packages/tokens/src/themes.test.ts)
- [`apps/mobile/src/platform/theme/appearance.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/apps/mobile/src/platform/theme/appearance.ts)
- [`apps/mobile/src/features/appearance/appearance.screen.tsx`](https://github.com/CarlosZiegler/autofolio/blob/main/apps/mobile/src/features/appearance/appearance.screen.tsx)
- [`packages/api/src/features/vehicle-photo/vehicle-photo.color.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/packages/api/src/features/vehicle-photo/vehicle-photo.color.ts)
- [`apps/web/src/features/app-shell/app-shell.appearance.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/apps/web/src/features/app-shell/app-shell.appearance.ts)

