# review-mockup — E250-C0060

**Aprobada:** `v1-inline.html`
**Motivo:** el fix de fidelidad de tema (bloqueante en la ronda anterior) está correcto: el primary resuelve al verde de marca e250 `#2eac66`, verificado en runtime. Cubre todos los criterios visuales del contrato. v1 (edición inline) gana a v2 (modal) por menos fricción para el flujo real de 4 integraciones cortas con guardado por tarjeta.

## Verificación del fix (ronda 2)

Servido por HTTP local y abierto con Playwright (`getComputedStyle`), **ambas** variantes:

- `getComputedStyle(document.documentElement)['--p']` = `66.006958% 0.149943 153.947211` → hue **153.95** (verde), NO el violeta ~276 del default DaisyUI. ✅
- Botón "Editar" (outline): color de texto `oklch(0.66007 0.149943 153.947)` = verde `#2eac66`. ✅
- Botón "Guardar" (filled): background `oklch(0.66007 0.149943 153.947)` = verde `#2eac66`. ✅
- Confirmado visualmente en captura: "Editar"/"Guardar", badge "Editando" (v1) y borde de tarjeta activa son verdes de marca; el badge `success` "Configurada" usa el `--su` del tema. Console sin errores en v2 (v1 sólo el warning esperado del CDN de Tailwind, irrelevante para el mockup).

El bloque inyectado `[data-theme="e250"] { --p / --s / --a / --su / --wa / --er ... }` deriva de los hex reales de `packages/widget/tailwind.config.js` (`daisyui.themes.e250`) — verificado token a token contra el config real. Fix bien resuelto.

## Re-evaluación de criterios visuales del contrato (ojo fresco)

Ambas variantes cumplen:

- **Lectura por defecto, sin inputs abiertos.** Las tarjetas nacen en lectura; sólo una está en edición a modo de ilustración (v1: Stripe inline; v2: modal de Stripe abierto). ✅
- **Estado por integración de un vistazo.** Badge `Configurada` (success, verde) / `Falta configurar` (warning, naranja) por tarjeta. ✅
- **Estado por campo.** Clear muestra su valor (Base URL, Capabilities, From address, recipients); secreto muestra `✓ Configurado` (badge-ghost) o `Sin configurar` (badge-error, v2 Stripe webhook) — nunca el valor. ✅
- **Botón "Editar" explícito por tarjeta** que abre los inputs. ✅ (con la nota de que en el panel real sólo lo ve `auth.canWrite`, ya recogida en el pie de página del mockup).
- **Sólo campos necesarios.** Ambos omiten los overrides de testing (Stripe `apiHost`/`apiPort`/`apiProtocol`, Resend `baseUrl`); el pie de página lo hace explícito. ✅
- **Fidelidad al shell e250.** Clases DaisyUI calcadas del SFC real (`card bg-base-100 border border-base-300 shadow-sm`, `card-body`, `card-title text-base`, `form-control`, `label py-1`, `label-text-alt badge badge-ghost badge-sm`, `input input-bordered input-sm`, `card-actions` / `modal-action`). Tema e250 ahora correcto. ✅
- **Label de Resend recipients con el matiz "(separadas por comas)".** Presente y verificado en captura en ambas variantes: "Destinatarios de alertas internas (separadas por comas)". ✅ (finding de copy de la ronda anterior, resuelto).
- **Marca de mockup.** Banner-comentario en `<head>` + badge "MOCKUP — no producción" arriba del fold en ambas. ✅

## Findings por variante

### v1-inline.html (aprobada)
- ✅ Tema e250 (verde) correcto, DaisyUI semántico fiel al SFC real, banner+badge de mockup, label "(separadas por comas)" presente.
- ✅ Modo edición inline (Stripe) con `border-2 border-primary` + badge "Editando", `card-actions justify-end` con Cancelar (`btn-ghost`) + Guardar (`btn-primary`).
- Sin findings bloqueantes ni menores pendientes.

### v2-modal.html (no elegida; sin defectos)
- ✅ Tema e250 (verde) correcto en lista y modal; modal DaisyUI bien usado (`modal modal-open`, `modal-box`, `modal-action`, `modal-backdrop`); Stripe en lectura ilustra bien el estado por campo (`Sin configurar` badge-error en el webhook).
- No se elige sólo por el eje modal: con 4 integraciones cortas y guardado por tarjeta, la expansión inline de v1 mantiene todo el contexto en una página sin overlay. v2 escala mejor si crecen los campos, pero hoy añade fricción innecesaria.

## Veredicto
**aprobado: `v1-inline.html`** — fix de tema confirmado (primary verde `#2eac66`, hue 153.9) y todos los criterios visuales del contrato cumplidos. Listo para promover a `to-do/`.

## Notas para la fase de implementación TDD (build-frontend)
- El SFC real `PanelIntegrationsView.vue` hoy renderiza **siempre** el formulario abierto. Este change introduce el toggle lectura↔edición por tarjeta: estado `editing[integ.id]` reactivo, botón "Editar" (sólo bajo `auth.canWrite`) que lo activa, y Cancelar que lo desactiva re-sembrando el draft (`seedDrafts` por integración) sin guardar.
- Estado por campo en lectura derivado de `IntegrationFieldView`: clear → `field.value`; secreto → `field.hasValue ? '✓ Configurado' : 'Sin configurar'`. Estado a nivel integración (`Configurada` / `Falta configurar`) = todos los campos visibles tienen valor. "Todo campo visible cuenta como requerido" (criterio del contrato).
- Overrides retirados de la vista (Stripe `apiHost/apiPort/apiProtocol`, Resend `baseUrl`) deben filtrarse en la **superficie** (vista o proyección backend), conservando su resolución vía `IntegrationConfigPort.resolve(...)` para que los tests que apuntan a un mock sigan funcionando (fuera-de-alcance: no se toca el override en los consumidores).
- Conservar `data-testid` existentes y la semántica write-only de secretos al guardar (campo vacío = no enviar).
- Todo copy (badges de estado, "Editar", "Cancelar", labels incl. "(separadas por comas)") va por i18n (`panel.integrations.*`), no hardcodeado — el mockup sólo refleja el copy, no lo reinventa.
