# L5 — WebP responsivo via middleware (sem toque nos módulos)

**Objetivo:** otimizar imagens (WebP responsivo + `<picture>`) sem editar os Blades dos módulos e
sem depender do dev. A transformação é global (middleware de resposta) e a geração de variantes roda
em background para imagens já cadastradas e futuras.

## Como funciona

1. **Upload (futuro):** todo upload passa por `FileTrait::compress()`, que agora chama
   `generateWebpVariants()` → gera `variants/{base}-{360,720,1200,1920}w.webp` (+ `original` p/ <360px)
   e o sidecar `variants/{base}.variants.json` (mapa largura → caminho relativo). Idempotente.
2. **Background (existente):** `php artisan images:redigest-webp --limit=300` (agendado
   `everyTenMinutes` em `app/Console/Kernel.php`) digeste o acervo em chunks e "dá a volta" (offset
   em `.webp_redigest_offset`) — cobre imagens cadastradas e futuras de forma contínua.
3. **Render (global):** `PictureTransform` (grupo `web`, após `CacheControl`) reescreve `<img>` de
   imagem local em `<picture>` com `<source type="image/webp">` + `<img>` fallback. Se a imagem ainda
   não tem sidecar, o `<img>` original é mantido — o background a otimiza na próxima corrida.

## Arquivos

- `app/Http/Middleware/PictureTransform.php` — transforma `<img>` → `<picture>` (anti double-download:
  `loading="lazy"` no fallback; `fetchpriority="high"` no 1º `<source>` se a imagem era `eager`/LCP).
- `app/Http/Traits/FileTrait.php` — `generateWebpVariants()` (hook em `compress()`).
- `app/Console/Commands/RedigestWebpImages.php` — digestão em background.
- `app/Console/Kernel.php` — agendamento `everyTenMinutes`.
- `app/Http/Kernel.php` — registro do middleware no grupo `web`.
- `public/.htaccess` — `AddType image/webp .webp` (+ `image/avif`).

## Detalhes de correção

- **Engine:** Intervention com driver **Imagick** (verificado `WEBP_OK` no container PHP 7.2). Quality 82.
- **EXIF:** `stripImage()` no core para reduzir tamanho.
- **Pular:** `svg` (vetorial) e **GIF animado** (preserva animação).
- **MIME:** sem `AddType image/webp` o Apache servia `.webp` sem `Content-Type` → navegador (nosniff)
  recusava. Corrigido em `public/.htaccess`.

## Validação

- Homepage do canário: 6 `<picture>` com `type="image/webp"`, `<img>` `loading="lazy"` +
  `data-webp="optimized"`, atributos originais preservados.
- Variantes servidas como `Content-Type: image/webp` (HTTP 200).
- `images:redigest-webp` idempotente (sidecar poblado → retorna sem reprocessar).

## Pendências

- Medir no canário (`medir_estrutura.sh` + `comparar.py`): `transfer` ↓, `lcp` < 2500.
- §6 D (CSP) e E (fontes/CLS) ainda pendentes (segurança adiada).
- Imagens em `incorporacao_head`/`rodape` (DB) não recebem `<picture>` (auditar).

## Preload do LCP (anti double-download)

Para a 1ª `<img>` `eager`/`fetchpriority="high"` da página (candidata a LCP), o
middleware injeta no `<head>` um `<link rel="preload" as="image" type="image/webp"
fetchpriority="high">` **por variante**, cada um com o MESMO `media` da `<source>`
correspondente:

- variantes > menor largura → `media="(min-width: Wpx)"` (igual à `<source>`);
- menor variante (source default, sem `media` na `<picture>`) →
  `media="(max-width: {proxLargura-1}px)"`, espelhando o intervalo em que o
  `<picture>` de fato a seleciona.

Assim, em qualquer viewport **apenas uma** variante é pré-carregada — sem
double-download e sem desperdício. Imagens `lazy` não recebem preload. AVIF não
é usado (Imagick deste build não suporta; tier é WebP → JPEG original).

## Revisão de conformidade (skills php-72 / laravel-55 / web-performance / a11y)

- **PHP 7.2:** corrigido `str_contains()` (8.0) → `strpos()`; `declare(strict_types=1)`
  em `PictureTransform`, `RedigestWebpImages` e `FileTrait`; sem arrow fn / typed
  props / match / union / nullsafe / `??=`.
- **Laravel 5.5:** middleware no grupo `web` após `CacheControl`; command
  `$signature`/`$description`/`handle():int`; `schedule()->everyTenMinutes()`;
  sem `env()` em código.
- **Web a11y:** `alt` preservado verbatim (sem re-escape); `role="img"` redundante
  removido (implícito do `<img>`); `width`/`height` anti-CLS; sem imagem grande
  com `alt=""`.
- **Web performance:** `width`/`height` (CLS), `loading="lazy"`+`decoding="async"`
  abaixo da dobra, `fetchpriority="high"` no LCP, preload do LCP, `<picture>`
  WebP → JPEG. Verificado em canário via sniffCSS (attrs + regras).
