# Юридические страницы (`entities/legal-doc`)

Общий механизм для **пяти статичных юридических страниц**. Раньше каждая была
самостоятельным `.tsx` с захардкоженной разметкой (200–300 строк JSX) и почти
идентичным собственным `.module.css`. После рефакторинга весь текст вынесен в
**данные** (`LegalDoc`-объекты), а рендерит их **один шаблон** `LegalDoc` с единым
стилем. Результат пункта чек-листа `app/providers/ROUTES_REFACTOR.md` → «Юридические
страницы … статичный текст вынести в данные, рендерить общим шаблоном».

## Какие страницы

| Маршрут (`ROUTES`) | Страница (`pages/*`) | Данные | h1 |
|---|---|---|---|
| `/publichnaya-oferta` | `publichnaya-oferta` | `model/content.ts → publichnayaOfertaDoc` | ПУБЛИЧНЫЙ ДОГОВОР ОФЕРТЫ |
| `/politika-personalnyh-dannyh` | `politika-personalnyh-dannyh` | `politikaPersonalnyhDannyhDoc` | ПОЛИТИКА ОБРАБОТКИ ПД |
| `/politika-cookie` | `politika-cookie` | `politikaCookieDoc` | ПОЛИТИКА COOKIE |
| `/soglasie-personalnyh-dannyh` | `soglasie-personalnyh-dannyh` | `soglasieDoc` | СОГЛАСИЕ НА ОБРАБОТКУ ПД |
| `/reestr-pd-rkn` | `reestr-pd-rkn` | `reestrDoc` | Реестр операторов ПД |

Все пять — **публичные** (вне `ProtectedRoute`/`GuestRoute`), подключены в
`app/providers/RouterProvider.tsx`.

## Архитектура (FSD: `pages → entities`)

```
entities/legal-doc/              ← общий, переиспользуемый механизм (без контента)
  model/types.ts                 ← типы LegalDoc / LegalSection / LegalBlock
  ui/LegalDoc.tsx                ← единый рендерер (main→container→title→sections→blocks)
  ui/LegalDoc.module.css         ← единый стиль (слит из 5 старых модулей)
  index.ts                       ← export { LegalDoc }, типы (LegalDocData = тип данных)
  README.md                      ← этот файл

pages/<slug>/                    ← каждая страница = контент + тонкая обёртка
  model/content.ts               ← <slug>Doc: LegalDocData — ВЕСЬ текст страницы
  ui/<Name>Page.tsx              ← <Header/> <LegalDoc doc={<slug>Doc}/> <Footer/>
  index.ts                       ← export { <Name>Page }  (не менялся)
```

> **Почему `entities`, а не `widgets`.** `Header`/`Footer` — это виджеты. Если бы шаблон
> рендерил их сам, он стал бы виджетом, импортирующим другие виджеты (межвиджетный импорт,
> который другой пункт чек-листа просит как раз убирать). Поэтому `LegalDoc` рендерит
> **только тело** документа (`<main>…`), а `Header`/`Footer` добавляет страница-обёртка.
> Слой `entities` ниже `widgets` — нарушения порядка слоёв нет. Структура повторяет
> соседний `entities/commission` (`model/` + `ui/` + barrel).

## Модель данных (`model/types.ts`)

```ts
LegalDoc = { title: string; subtitle?: string; sections: LegalSection[] }
LegalSection = { title?: string; blocks: LegalBlock[] }   // title → h3; нет title → секция без заголовка
```

`LegalBlock` — размеченный union (поле `kind`). Порядок блоков в массиве = порядок на
экране (подзаголовки и абзацы чередуются как в исходнике).

| `kind` | Поля | Рендер | Где используется |
|---|---|---|---|
| `text` | `text`, `variant?` | `<p class=text>` | везде |
| `subheading` | `text` | `<h4 class=subheading>` (был `subSectionTitle`) | политики, согласие, cookie |
| `list` | `items: LegalListItem[]` | `<ul class=list>` | везде |
| `definitions` | `items: {term,text}[]` | боксы с левым акцентом | оферта, политика ПД |
| `goals` | `items: {title,items[]}[]` | боксы «заголовок + вложенный список» | политика ПД (раздел «Цели сбора») |
| `infoBox` | `lines: LegalListItem[]` | бокс из `<p>`-строк | реквизиты, контакты, данные оператора |
| `link` | `href`, `text` | центрированная кнопка-ссылка (`target=_blank`) | только реестр РКН |

`variant` у `text`: `'example'` (курсивный акцент-бокс), `'warning'` (жёлтый бокс),
`'emphasis'` (полужирный абзац, был `.confirmation`). Без `variant` — обычный абзац.

`LegalListItem` = либо строка, либо `{ strong, text? }` (жирный зачин + остаток).
Используется в `list` и в `infoBox`.

### Важный нюанс: разделитель (`—`, `–`, `:`) хранится в данных

Рендерер `{strong,text}` выводит как `<strong>{strong}</strong> {text}` — **без** своего
разделителя. Поэтому тире/двоеточие пишется прямо в данных:
- cookie: `{ strong: 'Добровольность', text: '— согласие дается…' }` → «**Добровольность** — …»
- реестр: `{ strong: 'ИНН:', text: '9810001062' }` → «**ИНН:** 9810001062»

Аналогично у `definitions` тире входит в `text` (`{ term: 'Агент', text: '– юридическое лицо…' }`),
т.к. в оферте `–` (en-dash), а в политике ПД `—` (em-dash) — единый разделитель в коде
исказил бы исходник.

## Что изменилось визуально (унификация стилей)

Пять старых `.module.css` были на 90% одинаковы. При слиянии разнобойные боксы
`requisites` / `info` / `contacts` / `operatorInfo` сведены к одному классу `.infoBox`
(фон-стекло + левый акцент). Единственное реальное изменение: у **реквизитов оферты**
раньше была сплошная рамка, теперь — левый акцент, как у остальных боксов.

> Сохранён как было (намеренно, чтобы рефакторинг не менял поведение): `text variant=warning`
> — светло-жёлтый фон `#fff3cd` с белым текстом (низкий контраст). Это исторический баг
> исходного cookie-CSS; чинить — отдельной задачей, не в рамках этого пункта.

## Как добавить / отредактировать страницу

- **Поправить текст** — только `pages/<slug>/model/content.ts`. Шаблон и стиль не трогать.
- **Новая юридическая страница** — добавить `ROUTES`, `<Route>` в `RouterProvider`,
  папку `pages/<slug>` с `model/content.ts` (объект `LegalDocData`) и тонкой обёрткой
  `<Header/> <LegalDoc doc={…}/> <Footer/>`. Новых CSS-файлов не нужно.
- **Новый тип блока** — добавить вариант в `LegalBlock` (`model/types.ts`), ветку в
  `Block` (`ui/LegalDoc.tsx`) и стиль в `ui/LegalDoc.module.css`.

## Проверка

```bash
npm run build   # tsc -b + vite build (тестов в проекте нет)
npm run lint
npm run dev     # ручная проверка пяти /publichnaya-oferta, /politika-*, /soglasie-*, /reestr-pd-rkn
```
