# Build brief — keywords/recherche

> Gabarit court, orienté build. CdC complet (source de vérité) : `keywords/recherche` (mémoire specs).
> **Triage/ciblage, pas découverte.** Source = le Reservoir déjà rempli.

- **Route** : `/keywords/recherche` (route group `(app)`).
- **But** : depuis le Reservoir d'un site, **sélectionner** des keywords, leur **assigner des pays cibles** (multi), et lire la **couverture `keyword × pays`**.

## Périmètre — lot 1 (ce build)

**Dans** : vue **liste** (reskin du template Reservoir) · vue **matrice** `keyword × pays` · **toggle** liste↔matrice · **ciblage multi-pays** (bulk depuis la liste + clic-cellule dans la matrice).

**Reporté (lots suivants)** : métriques *par pays* (F5/détail cellule), gaps + expansion inter-pays (F6), suggestions saisonnières (F7), shortlist/panier (F8), push-planning réel (F9), analytics d'avancement (F10), virtualisation.

## Écran

- En-tête : titre + **toggle Liste | Matrice** ; sélecteur de site (déjà dans le shell).
- **Vue liste** : `DataTable` réutilisé (colonnes Reservoir + colonne **« Pays ciblés »**), `FiltersBar` réutilisé, `TargetingBar` (multi-select pays + bouton **Cibler**) à la sélection, `KeywordSheet` réutilisé au clic ligne.
- **Vue matrice** : vrai `<table>` a11y — terme = en-tête de **ligne** (`scope="row"`), pays = en-têtes de **colonne** (`scope="col"`, avec flag). Cellule = badge de statut ou « — » ; **clic → menu** (`— / candidat / planifié / en ligne`).

## Données (mock)

- `TargetStatus = candidate | planned | live` (absence = **non ciblé**).
- `TARGET_COUNTRIES = US 🇺🇸 · GB 🇬🇧 · CA 🇨🇦 · AU 🇦🇺` (jeu fixe pour le proto ; cadré-par-`site.locales` vs libre = question API réelle).
- `TargetsState = Record<keywordId, Partial<Record<country, TargetStatus>>>` — **state client**, seed déterministe, **reset au switch de site** (cohérent Reservoir, pas de persistance).
- Helpers **purs** : `seedTargets`, `setCell`, `setForSelected`, `coverageOf`.

## Composants

`DataTable` · `FiltersBar` · `metric-badge`/`sparkline`/`status-badge` · `KeywordSheet` (réutilisés) · **nouveaux** : `ResearchContainer` · `CoverageMatrix` · `TargetingBar` · `TargetStatusBadge` · `research-columns` (colonnes liste = Reservoir + « Pays ciblés ») · Tabs (toggle).

## Filtrage

La **recherche texte filtre les deux vues**. Les filtres riches (thème/intent/plages) restent **vue liste** pour ce lot.

## États

Vide (« aucun keyword pour ce site ») · chargement (skeleton réutilisé). Erreur n/a (mock).

## Critères d'acceptation (proto)

- Le **toggle** bascule liste↔matrice sans perdre l'état des cibles.
- Sélectionner N lignes + choisir des pays + **Cibler** crée N×pays cibles en `candidate`, visibles dans les deux vues.
- Dans la matrice, **clic sur une cellule** ouvre le menu et change le statut (y compris remise à « non ciblé »).
- La **recherche texte** filtre liste **et** matrice.
- Le **switch de site** isole tout (aucune cible d'un autre site) et re-seed.
- Clavier + focus visibles (matrice = tableau sémantique row+col scope).

## Hors proto

API réelle, persistence, dédup/merge, métriques par pays réelles, re-check Google.
