#!/usr/bin/env python3
"""
Batch dos 11 criativos restantes (02–12) — Cloud PhotoRF 2.0, feed 1:1 (1080x1080).
Mantém a identidade do piloto (preto #0a0a0c, verde #A6E22E, Barlow+Montserrat+JetBrains,
selo "PREPARE-SE PARA O ABSURDO!", wordmark, brackets de detecção, data 07.10)
e varia composição/foco/tratamento conforme regra do Renato.

CTA rotacionado entre os 11 (piloto 01 permanece com "QUERO VER ANTES"):
  - "QUERO VER ANTES →"              (3x: 03, 06, 09)
  - "ENTRAR PARA A LISTA DE ESPERA →"(4x: 02, 05, 08, 11)
  - "QUERO SER UM DOS PRIMEIROS →"   (4x: 04, 07, 10, 12)

Autor: Juliana (juliana-ops) — Agência Climb Digital
"""

from __future__ import annotations

import base64
from dataclasses import dataclass
from pathlib import Path
from typing import Callable
from playwright.sync_api import sync_playwright
from PIL import Image

BASE = Path("/opt/mia/workspace/clientes/px3lab/criativos_lancamento_1007")
ASSET_FORMANDA = Path("/opt/mia/workspace/clientes/px3lab/catalogos/crops/formanda_face_brackets.png")
ASSET_FORMANDA_FULL = Path("/opt/mia/workspace/clientes/px3lab/catalogos/crops/formanda_full_clean.png")
ASSET_LOGO = Path("/opt/mia/workspace/clientes/px3lab/landing_lancamento_novo/preview-lp/assets/logo-wordmark.png")


def b64_img(path: Path) -> str:
    data = path.read_bytes()
    ext = path.suffix.lstrip(".").lower()
    if ext == "jpg":
        ext = "jpeg"
    return f"data:image/{ext};base64," + base64.b64encode(data).decode()


FORMANDA_B64 = b64_img(ASSET_FORMANDA)
FORMANDA_FULL_B64 = b64_img(ASSET_FORMANDA_FULL)
LOGO_B64 = b64_img(ASSET_LOGO)


# =============================================================================
# CSS compartilhado — identidade visual fixa
# =============================================================================

CSS_BASE = """
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700;800;900&family=Montserrat:wght@600;700;800;900&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; }
  html, body { width: 1080px; height: 1080px; overflow: hidden; background: #0a0a0c; font-family: 'Montserrat', sans-serif; -webkit-font-smoothing: antialiased; }

  .canvas {
    position: relative;
    width: 1080px; height: 1080px;
    background:
      radial-gradient(circle at var(--rx, 72%) var(--ry, 42%), rgba(135,201,37,0.08) 0%, rgba(10,10,12,0) 55%),
      linear-gradient(180deg, #0f0f12 0%, #0a0a0c 100%);
    overflow: hidden;
  }

  /* grid tech sutil variavel */
  .grid-bg {
    position: absolute; inset: 0;
    background-image:
      linear-gradient(rgba(135,201,37,0.045) 1px, transparent 1px),
      linear-gradient(90deg, rgba(135,201,37,0.045) 1px, transparent 1px);
    background-size: 60px 60px;
    mask-image: radial-gradient(ellipse 70% 60% at 50% 50%, #000 40%, transparent 100%);
    -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 50%, #000 40%, transparent 100%);
  }
  .grid-bg.dots {
    background-image: radial-gradient(rgba(166,226,46,0.14) 1.4px, transparent 1.4px);
    background-size: 28px 28px;
  }
  .grid-bg.lines-h {
    background-image: linear-gradient(rgba(166,226,46,0.055) 1px, transparent 1px);
    background-size: 100% 48px;
  }
  .grid-bg.crosshair {
    background-image:
      linear-gradient(rgba(166,226,46,0.03) 1px, transparent 1px),
      linear-gradient(90deg, rgba(166,226,46,0.03) 1px, transparent 1px),
      radial-gradient(rgba(166,226,46,0.22) 2px, transparent 2px);
    background-size: 40px 40px, 40px 40px, 240px 240px;
    background-position: 0 0, 0 0, 20px 20px;
  }

  /* HEADER */
  .header {
    position: absolute;
    top: 56px; left: 60px; right: 60px;
    display: flex; align-items: center; justify-content: space-between;
    z-index: 10;
  }
  .selo-campanha {
    font-family: 'Barlow Condensed', sans-serif;
    font-weight: 900;
    font-size: 22px;
    letter-spacing: 0.14em;
    color: #ffffff;
    text-transform: uppercase;
    display: flex; align-items: center; gap: 10px;
  }
  .selo-campanha .absurdo { color: #A6E22E; }
  .selo-campanha .bar {
    display: inline-block;
    width: 4px; height: 22px;
    background: #A6E22E;
    transform: skewX(-18deg);
    margin-right: 4px;
  }
  .wordmark { height: 32px; opacity: 0.95; }

  /* Headline / sub padrão */
  .kicker {
    font-family: 'JetBrains Mono', monospace;
    font-weight: 500;
    font-size: 18px;
    letter-spacing: 0.18em;
    color: #A6E22E;
    margin-bottom: 24px;
    text-transform: uppercase;
    display: flex; align-items: center; gap: 12px;
  }
  .kicker::before {
    content: "";
    display: inline-block; width: 36px; height: 2px; background: #A6E22E;
  }
  .headline {
    font-family: 'Barlow Condensed', sans-serif;
    font-weight: 900;
    line-height: 0.92;
    letter-spacing: -0.015em;
    color: #ffffff;
    text-transform: uppercase;
    margin-bottom: 28px;
  }
  .headline .hl { color: #A6E22E; }
  .sub {
    font-family: 'Montserrat', sans-serif;
    font-weight: 600;
    font-size: 23px;
    line-height: 1.4;
    color: #d6d6d6;
    max-width: 560px;
  }
  .sub strong { color: #ffffff; font-weight: 800; }

  /* FOTO wrap */
  .photo-wrap {
    position: relative;
    border-radius: 14px;
    overflow: hidden;
    background: #000;
    box-shadow: 0 30px 60px rgba(0,0,0,0.5), 0 0 0 1px rgba(166,226,46,0.18);
  }
  .photo-wrap img.foto {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    filter: contrast(1.05) saturate(1.05);
  }
  .photo-wrap::after {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(10,10,12,0) 55%, rgba(10,10,12,0.85) 100%);
  }
  .photo-wrap.full-bleed::after {
    background: linear-gradient(180deg, rgba(10,10,12,0.1) 0%, rgba(10,10,12,0.4) 50%, rgba(10,10,12,0.92) 95%);
  }

  /* Brackets */
  .brk {
    position: absolute;
    width: 54px; height: 54px;
    border: 5px solid #A6E22E;
    z-index: 3;
    filter: drop-shadow(0 0 8px rgba(166,226,46,0.35));
  }
  .brk.sm { width: 36px; height: 36px; border-width: 4px; }
  .brk.lg { width: 72px; height: 72px; border-width: 6px; }
  .brk.tl { border-right: none; border-bottom: none; }
  .brk.tr { border-left: none; border-bottom: none; }
  .brk.bl { border-right: none; border-top: none; }
  .brk.br { border-left: none; border-top: none; }

  /* Pills */
  .status-pill {
    position: absolute;
    background: rgba(10,10,12,0.75);
    backdrop-filter: blur(6px);
    border: 1px solid rgba(166,226,46,0.4);
    border-radius: 999px;
    padding: 10px 18px;
    display: flex; align-items: center; gap: 10px;
    font-family: 'JetBrains Mono', monospace;
    font-weight: 700;
    font-size: 13px;
    color: #A6E22E;
    letter-spacing: 0.08em;
    z-index: 4;
  }
  .status-pill .dot {
    width: 8px; height: 8px; background: #A6E22E;
    border-radius: 50%;
    box-shadow: 0 0 10px #A6E22E;
  }
  .status-pill.neutral { border-color: rgba(255,255,255,0.3); color: #fff; }
  .status-pill.neutral .dot { background: #fff; box-shadow: 0 0 10px #fff; }

  .launch-tag {
    position: absolute;
    font-family: 'JetBrains Mono', monospace;
    font-weight: 700;
    font-size: 12px;
    color: #ffffff;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    background: rgba(0,0,0,0.55);
    padding: 6px 10px;
    border-radius: 4px;
    z-index: 4;
  }

  /* FOOTER */
  .footer {
    position: absolute;
    left: 60px; right: 60px; bottom: 60px;
    display: flex; align-items: center; justify-content: space-between;
    gap: 20px;
    z-index: 10;
  }
  .cta {
    background: #A6E22E;
    color: #0a0a0c;
    font-family: 'Montserrat', sans-serif;
    font-weight: 900;
    font-size: 22px;
    letter-spacing: 0.03em;
    padding: 20px 32px;
    border-radius: 10px;
    text-transform: uppercase;
    display: inline-flex; align-items: center; gap: 14px;
    box-shadow: 0 10px 30px rgba(166,226,46,0.25);
    white-space: nowrap;
    line-height: 1;
  }
  .cta.sm { font-size: 18px; padding: 18px 26px; letter-spacing: 0.02em; }
  .cta.md { font-size: 20px; padding: 19px 28px; }
  .cta .arrow { font-size: 26px; line-height: 1; }

  .meta-line {
    display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
  }
  .meta-line .label {
    font-family: 'JetBrains Mono', monospace;
    font-weight: 500;
    font-size: 12px;
    color: #8a8a90;
    letter-spacing: 0.18em;
    text-transform: uppercase;
  }
  .meta-line .date {
    font-family: 'Barlow Condensed', sans-serif;
    font-weight: 900;
    font-size: 44px;
    color: #ffffff;
    letter-spacing: 0.02em;
    line-height: 1;
  }
  .meta-line .date .accent { color: #A6E22E; }
  .meta-line .bar2 {
    display: inline-block;
    width: 3px; height: 36px; background: #A6E22E;
    transform: skewX(-14deg);
    margin-right: 10px;
    vertical-align: middle;
  }
</style>
"""


HEADER_HTML = f"""
<div class="header">
  <div class="selo-campanha">
    <span class="bar"></span>
    PREPARE-SE PARA O <span class="absurdo">ABSURDO!</span>
  </div>
  <img class="wordmark" src="{LOGO_B64}" alt="Cloud PhotoRF 2.0">
</div>
"""


def footer_html(cta_text: str) -> str:
    """Monta footer com CTA dinâmico. Ajusta tamanho conforme comprimento do texto
    pra manter o pill de data visível sem quebrar linha no botão."""
    # tira a seta pra medir o texto
    base = cta_text.rstrip("→ ").strip()
    length = len(base)
    if length <= 14:
        cta_class = ""         # grande (ex.: "QUERO VER ANTES")
    elif length <= 24:
        cta_class = "md"       # médio (ex.: "QUERO SER UM DOS PRIMEIROS")
    else:
        cta_class = "sm"       # pequeno (ex.: "ENTRAR PARA A LISTA DE ESPERA")
    return f"""
<div class="footer">
  <div class="cta {cta_class}">
    {base}
    <span class="arrow">→</span>
  </div>
  <div class="meta-line">
    <span class="label">Lançamento</span>
    <span class="date"><span class="bar2"></span>07<span class="accent">.</span>10<span class="accent">.</span>26</span>
  </div>
</div>
"""


# =============================================================================
# TEMPLATES de layout
# =============================================================================

def tpl_split_right(kicker: str, headline_html: str, sub_html: str, pill_text: str,
                    tag_text: str, cta_text: str, headline_size: int = 118,
                    grid_class: str = "", img_pos: str = "50% 25%",
                    rx: str = "72%", ry: str = "42%", **_) -> str:
    """Split: texto à esquerda, foto à direita (igual piloto)."""
    return f"""<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">{CSS_BASE}
<style>
  .canvas {{ --rx:{rx}; --ry:{ry}; }}
  .stage {{
    position: absolute;
    top: 150px; bottom: 220px; left: 60px; right: 60px;
    display: grid;
    grid-template-columns: 1fr 440px;
    gap: 40px;
    align-items: center;
  }}
  .copy {{ display: flex; flex-direction: column; justify-content: center; height: 100%; }}
  .headline {{ font-size: {headline_size}px; }}
  .photo-wrap {{ width: 440px; height: 580px; }}
  .photo-wrap img.foto {{ object-position: {img_pos}; }}
  .brk.tl {{ top:24px; left:24px; }}
  .brk.tr {{ top:24px; right:24px; }}
  .brk.bl {{ bottom:24px; left:24px; }}
  .brk.br {{ bottom:24px; right:24px; }}
  .status-pill {{ bottom: 90px; left: 24px; }}
  .launch-tag {{ top: 24px; right: 90px; }}
</style></head><body>
<div class="canvas">
  <div class="grid-bg {grid_class}"></div>
  {HEADER_HTML}
  <div class="stage">
    <div class="copy">
      <div class="kicker">{kicker}</div>
      <h1 class="headline">{headline_html}</h1>
      <p class="sub">{sub_html}</p>
    </div>
    <div class="photo-wrap">
      <img class="foto" src="{FORMANDA_B64}" alt="">
      <div class="brk tl"></div><div class="brk tr"></div>
      <div class="brk bl"></div><div class="brk br"></div>
      <div class="launch-tag">{tag_text}</div>
      <div class="status-pill"><span class="dot"></span>{pill_text}</div>
    </div>
  </div>
  {footer_html(cta_text)}
</div></body></html>"""


def tpl_split_left(kicker: str, headline_html: str, sub_html: str, pill_text: str,
                   tag_text: str, cta_text: str, headline_size: int = 118,
                   grid_class: str = "", img_pos: str = "50% 20%",
                   rx: str = "28%", ry: str = "42%", **_) -> str:
    """Split: foto à esquerda, texto à direita."""
    return f"""<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">{CSS_BASE}
<style>
  .canvas {{ --rx:{rx}; --ry:{ry}; }}
  .stage {{
    position: absolute;
    top: 150px; bottom: 220px; left: 60px; right: 60px;
    display: grid;
    grid-template-columns: 440px 1fr;
    gap: 40px;
    align-items: center;
  }}
  .copy {{ display: flex; flex-direction: column; justify-content: center; height: 100%; }}
  .headline {{ font-size: {headline_size}px; }}
  .photo-wrap {{ width: 440px; height: 580px; }}
  .photo-wrap img.foto {{ object-position: {img_pos}; }}
  .brk.tl {{ top:24px; left:24px; }}
  .brk.tr {{ top:24px; right:24px; }}
  .brk.bl {{ bottom:24px; left:24px; }}
  .brk.br {{ bottom:24px; right:24px; }}
  .status-pill {{ bottom: 90px; left: 24px; }}
  .launch-tag {{ top: 24px; right: 24px; }}
</style></head><body>
<div class="canvas">
  <div class="grid-bg {grid_class}"></div>
  {HEADER_HTML}
  <div class="stage">
    <div class="photo-wrap">
      <img class="foto" src="{FORMANDA_B64}" alt="">
      <div class="brk tl"></div><div class="brk tr"></div>
      <div class="brk bl"></div><div class="brk br"></div>
      <div class="launch-tag">{tag_text}</div>
      <div class="status-pill"><span class="dot"></span>{pill_text}</div>
    </div>
    <div class="copy">
      <div class="kicker">{kicker}</div>
      <h1 class="headline">{headline_html}</h1>
      <p class="sub">{sub_html}</p>
    </div>
  </div>
  {footer_html(cta_text)}
</div></body></html>"""


def tpl_hero_vertical(kicker: str, headline_html: str, sub_html: str, pill_text: str,
                      tag_text: str, cta_text: str, headline_size: int = 150,
                      grid_class: str = "", img_pos: str = "50% 18%",
                      rx: str = "50%", ry: str = "35%", **_) -> str:
    """Hero vertical: foto full-bleed de fundo, texto overlay centralizado abaixo."""
    return f"""<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">{CSS_BASE}
<style>
  .canvas {{ --rx:{rx}; --ry:{ry}; }}
  .photo-bg {{
    position: absolute; inset: 0;
    overflow: hidden;
  }}
  .photo-bg img.foto {{
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    object-position: {img_pos};
    filter: contrast(1.05) saturate(0.95) brightness(0.82);
  }}
  .photo-bg::after {{
    content: "";
    position: absolute; inset: 0;
    background:
      linear-gradient(180deg, rgba(10,10,12,0.45) 0%, rgba(10,10,12,0.1) 30%, rgba(10,10,12,0.55) 60%, rgba(10,10,12,0.98) 92%);
  }}
  .copy {{
    position: absolute;
    left: 60px; right: 60px;
    bottom: 190px;
    text-align: left;
  }}
  .headline {{ font-size: {headline_size}px; max-width: 900px; }}
  .sub {{ max-width: 760px; }}
  .brk.tl {{ top: 150px; left: 60px; }}
  .brk.tr {{ top: 150px; right: 60px; }}
  .status-pill {{ top: 160px; right: 60px; }}
  .launch-tag {{ top: 150px; left: 60px; display: none; }}
</style></head><body>
<div class="canvas">
  <div class="photo-bg">
    <img class="foto" src="{FORMANDA_FULL_B64}" alt="">
  </div>
  <div class="grid-bg {grid_class}"></div>
  {HEADER_HTML}
  <div class="brk lg tl"></div><div class="brk lg tr"></div>
  <div class="status-pill"><span class="dot"></span>{pill_text}</div>
  <div class="copy">
    <div class="kicker">{kicker}</div>
    <h1 class="headline">{headline_html}</h1>
    <p class="sub">{sub_html}</p>
  </div>
  {footer_html(cta_text)}
</div></body></html>"""


def tpl_text_top(kicker: str, headline_html: str, sub_html: str, pill_text: str,
                 tag_text: str, cta_text: str, headline_size: int = 128,
                 grid_class: str = "", img_pos: str = "50% 22%",
                 rx: str = "50%", ry: str = "75%", **_) -> str:
    """Split horizontal: texto grande em cima, faixa de foto embaixo."""
    return f"""<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">{CSS_BASE}
<style>
  .canvas {{ --rx:{rx}; --ry:{ry}; }}
  .copy {{
    position: absolute;
    top: 160px; left: 60px; right: 60px;
    height: 460px;
    display: flex; flex-direction: column; justify-content: center;
  }}
  .headline {{ font-size: {headline_size}px; }}
  .photo-wrap {{
    position: absolute;
    left: 60px; right: 60px; bottom: 180px;
    height: 240px;
    border-radius: 12px;
  }}
  .photo-wrap img.foto {{ object-position: {img_pos}; }}
  .brk.sm.tl {{ top:16px; left:16px; }}
  .brk.sm.tr {{ top:16px; right:16px; }}
  .brk.sm.bl {{ bottom:16px; left:16px; }}
  .brk.sm.br {{ bottom:16px; right:16px; }}
  .status-pill {{ bottom: 18px; left: 18px; }}
  .launch-tag {{ top: 16px; right: 70px; }}
</style></head><body>
<div class="canvas">
  <div class="grid-bg {grid_class}"></div>
  {HEADER_HTML}
  <div class="copy">
    <div class="kicker">{kicker}</div>
    <h1 class="headline">{headline_html}</h1>
    <p class="sub">{sub_html}</p>
  </div>
  <div class="photo-wrap">
    <img class="foto" src="{FORMANDA_B64}" alt="">
    <div class="brk sm tl"></div><div class="brk sm tr"></div>
    <div class="brk sm bl"></div><div class="brk sm br"></div>
    <div class="launch-tag">{tag_text}</div>
    <div class="status-pill"><span class="dot"></span>{pill_text}</div>
  </div>
  {footer_html(cta_text)}
</div></body></html>"""


def tpl_mosaico(kicker: str, headline_html: str, sub_html: str, pill_text: str,
                tag_text: str, cta_text: str, headline_size: int = 128,
                grid_class: str = "", rx: str = "50%", ry: str = "50%", **_) -> str:
    """Mosaico 2x3 de miniaturas de rostos em fundo, headline centralizada por cima."""
    thumbs = []
    positions = [
        ("50% 22%", 0.55),
        ("50% 28%", 0.65),
        ("50% 20%", 0.50),
        ("50% 25%", 0.60),
        ("50% 30%", 0.70),
        ("50% 22%", 0.55),
        ("50% 26%", 0.60),
        ("50% 24%", 0.58),
    ]
    for pos, op in positions:
        thumbs.append(f'<div class="thumb" style="opacity:{op}"><img src="{FORMANDA_B64}" style="object-position:{pos}"></div>')
    thumbs_html = "\n".join(thumbs)
    return f"""<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">{CSS_BASE}
<style>
  .canvas {{ --rx:{rx}; --ry:{ry}; }}
  .mosaic {{
    position: absolute; inset: 150px 60px 220px 60px;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(2, 1fr);
    gap: 10px;
    z-index: 1;
  }}
  .thumb {{
    position: relative;
    overflow: hidden;
    border-radius: 8px;
    background: #111;
    border: 1px solid rgba(166,226,46,0.14);
  }}
  .thumb img {{ width: 100%; height: 100%; object-fit: cover; filter: grayscale(0.3) contrast(1.05) brightness(0.75); }}
  .thumb::after {{
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(10,10,12,0.1), rgba(10,10,12,0.6));
  }}
  .overlay {{
    position: absolute;
    inset: 150px 60px 220px 60px;
    background: radial-gradient(ellipse 60% 55% at 50% 50%, rgba(10,10,12,0.92) 40%, rgba(10,10,12,0.5) 100%);
    z-index: 2;
    display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;
    padding: 40px;
  }}
  .headline {{ font-size: {headline_size}px; text-align: center; }}
  .sub {{ text-align: center; max-width: 680px; }}
  .status-pill {{ bottom: auto; left: auto; top: 180px; right: 60px; }}
  .launch-tag {{ display: none; }}
</style></head><body>
<div class="canvas">
  <div class="grid-bg {grid_class}"></div>
  {HEADER_HTML}
  <div class="mosaic">{thumbs_html}</div>
  <div class="overlay">
    <div class="kicker" style="justify-content:center">{kicker}</div>
    <h1 class="headline">{headline_html}</h1>
    <p class="sub">{sub_html}</p>
  </div>
  <div class="status-pill"><span class="dot"></span>{pill_text}</div>
  {footer_html(cta_text)}
</div></body></html>"""


def tpl_close_bracket(kicker: str, headline_html: str, sub_html: str, pill_text: str,
                      tag_text: str, cta_text: str, headline_size: int = 118,
                      grid_class: str = "", img_pos: str = "50% 18%",
                      rx: str = "30%", ry: str = "60%", **_) -> str:
    """Zoom bracket só no canto, texto dominando."""
    return f"""<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">{CSS_BASE}
<style>
  .canvas {{ --rx:{rx}; --ry:{ry}; }}
  .photo-wrap {{
    position: absolute;
    top: 150px; right: 60px;
    width: 360px; height: 360px;
    border-radius: 50%;
    overflow: hidden;
  }}
  .photo-wrap img.foto {{ object-position: {img_pos}; }}
  .photo-wrap::after {{ background: linear-gradient(180deg, rgba(10,10,12,0) 60%, rgba(10,10,12,0.6) 100%); }}
  .brk.lg.tl {{ top:0; left:0; }}
  .brk.lg.br {{ bottom:0; right:0; }}
  .copy {{
    position: absolute;
    left: 60px; right: 60px; bottom: 200px;
    display: flex; flex-direction: column; justify-content: flex-end;
  }}
  .headline {{ font-size: {headline_size}px; max-width: 900px; }}
  .sub {{ max-width: 720px; }}
  .status-pill {{ top: 540px; right: 60px; }}
  .launch-tag {{ display: none; }}
</style></head><body>
<div class="canvas">
  <div class="grid-bg {grid_class}"></div>
  {HEADER_HTML}
  <div class="photo-wrap">
    <img class="foto" src="{FORMANDA_B64}" alt="">
    <div class="brk lg tl"></div><div class="brk lg br"></div>
  </div>
  <div class="status-pill"><span class="dot"></span>{pill_text}</div>
  <div class="copy">
    <div class="kicker">{kicker}</div>
    <h1 class="headline">{headline_html}</h1>
    <p class="sub">{sub_html}</p>
  </div>
  {footer_html(cta_text)}
</div></body></html>"""


def tpl_diagonal(kicker: str, headline_html: str, sub_html: str, pill_text: str,
                 tag_text: str, cta_text: str, headline_size: int = 118,
                 grid_class: str = "", img_pos: str = "50% 20%",
                 rx: str = "80%", ry: str = "25%", **_) -> str:
    """Divisão diagonal: foto em cunha superior-direita, texto em cunha inferior-esquerda."""
    return f"""<!doctype html><html lang="pt-BR"><head><meta charset="utf-8">{CSS_BASE}
<style>
  .canvas {{ --rx:{rx}; --ry:{ry}; }}
  .photo-wrap {{
    position: absolute;
    top: 140px; right: 60px;
    width: 540px; height: 540px;
    clip-path: polygon(14% 0%, 100% 0%, 100% 86%, 0% 100%);
    border-radius: 0;
    box-shadow: 0 20px 50px rgba(0,0,0,0.5);
  }}
  .photo-wrap img.foto {{ object-position: {img_pos}; }}
  .photo-wrap::after {{ background: linear-gradient(220deg, rgba(10,10,12,0) 55%, rgba(10,10,12,0.9) 100%); }}
  .brk.tl {{ top: 40px; left: 90px; }}
  .brk.br {{ bottom: 60px; right: 24px; }}
  .copy {{
    position: absolute;
    left: 60px; right: 540px; bottom: 190px;
    display: flex; flex-direction: column; justify-content: flex-end;
  }}
  .headline {{ font-size: {headline_size}px; }}
  .status-pill {{ bottom: 110px; right: 540px; }}
  .launch-tag {{ top: 160px; right: 100px; }}
</style></head><body>
<div class="canvas">
  <div class="grid-bg {grid_class}"></div>
  {HEADER_HTML}
  <div class="photo-wrap">
    <img class="foto" src="{FORMANDA_B64}" alt="">
    <div class="brk tl"></div><div class="brk br"></div>
    <div class="launch-tag">{tag_text}</div>
  </div>
  <div class="copy">
    <div class="kicker">{kicker}</div>
    <h1 class="headline">{headline_html}</h1>
    <p class="sub">{sub_html}</p>
  </div>
  <div class="status-pill"><span class="dot"></span>{pill_text}</div>
  {footer_html(cta_text)}
</div></body></html>"""


# =============================================================================
# ESPECIFICAÇÃO DOS 11 CRIATIVOS
# =============================================================================

@dataclass
class Spec:
    code: str
    slug: str
    template: Callable
    kicker: str
    headline_html: str
    sub_html: str
    pill_text: str
    tag_text: str
    cta_text: str
    headline_size: int = 118
    grid_class: str = ""
    img_pos: str = "50% 22%"
    rx: str = "72%"
    ry: str = "42%"


# =============================================================================
# CTAs rotacionados — definidos pelo Renato em 30/09/2026
# =============================================================================
CTA_VER_ANTES = "QUERO VER ANTES"
CTA_LISTA_ESPERA = "ENTRAR PARA A LISTA DE ESPERA"
CTA_PRIMEIROS = "QUERO SER UM DOS PRIMEIROS"


SPECS: list[Spec] = [
    # 02 — Processamento desatendido — split LEFT (inverte piloto)
    Spec(
        code="PX3-CLOUD-EST-02",
        slug="02_fila_rolando",
        template=tpl_split_left,
        kicker="Processamento desatendido",
        headline_html='FILA<br>ROLANDO.<br><span class="hl">VOCÊ, LIVRE.</span>',
        sub_html='Monta a fila, <strong>fecha o notebook</strong>, vai viver.<br>Volta e as fotos já estão separadas.',
        pill_text="PROCESSAMENTO ATIVO",
        tag_text="JOB · 047 · RUN",
        cta_text=CTA_LISTA_ESPERA,
        headline_size=118,
        grid_class="dots",
        img_pos="50% 20%",
    ),

    # 03 — Automação ponta a ponta — texto top + faixa foto
    Spec(
        code="PX3-CLOUD-EST-03",
        slug="03_babysitar",
        template=tpl_text_top,
        kicker="Automação ponta a ponta",
        headline_html='CHEGA DE <span class="hl">BABYSITAR</span><br>O SISTEMA.',
        sub_html='Carrega as fotos. <strong>Define a regra.</strong> Vai dormir.<br>O Cloud PhotoRF 2.0 entrega tudo pronto no dia seguinte.',
        pill_text="PIPELINE AUTO",
        tag_text="MODO · UNATTENDED",
        cta_text=CTA_VER_ANTES,
        headline_size=130,
        grid_class="lines-h",
        img_pos="50% 20%",
        rx="25%", ry="30%",
    ),

    # 04 — Verificação tripla — hero vertical
    Spec(
        code="PX3-CLOUD-EST-04",
        slug="04_verificacao_tripla",
        template=tpl_hero_vertical,
        kicker="Verificação em 3 camadas",
        headline_html='3 ETAPAS<br>DE VERIFICAÇÃO.<br><span class="hl">ZERO ERRO.</span>',
        sub_html='A IA confere. <strong>Confere de novo.</strong> Confere mais uma vez.<br>A foto só sai pro aluno quando é dele mesmo.',
        pill_text="VERIFIED · 03/03",
        tag_text="CHECK · PASS",
        cta_text=CTA_PRIMEIROS,
        headline_size=142,
        grid_class="crosshair",
        img_pos="50% 15%",
        rx="50%", ry="30%",
    ),

    # 05 — Formando esquecido — split right (igual piloto, headline nova)
    Spec(
        code="PX3-CLOUD-EST-05",
        slug="05_formando_esquecido",
        template=tpl_split_right,
        kicker="Fotos não identificadas",
        headline_html='AQUELE<br>FORMANDO<br><span class="hl">ESQUECIDO?</span><br>ACHOU.',
        sub_html='Resgate automático de <strong>fotos sem identificação</strong>.<br>A IA cruza, reconhece e devolve pra pasta certa.',
        pill_text="FACE RECOVERED",
        tag_text="ID · 112 · MATCH",
        cta_text=CTA_LISTA_ESPERA,
        headline_size=102,
        grid_class="",
        img_pos="50% 20%",
    ),

    # 06 — Parentes — mosaico
    Spec(
        code="PX3-CLOUD-EST-06",
        slug="06_parentes_sozinhos",
        template=tpl_mosaico,
        kicker="Reconhecimento de familiares",
        headline_html='FOTO DE PARENTE<br>SOZINHO?<br><span class="hl">A IA ACHA.</span>',
        sub_html='A mãe no corredor. O irmão na mesa.<br><strong>Todos encontram seu lote completo.</strong>',
        pill_text="FAMILY MATCH",
        tag_text="",
        cta_text=CTA_VER_ANTES,
        headline_size=108,
        grid_class="dots",
    ),

    # 07 — Olho fechado — close bracket (foto redonda) + headline forte
    Spec(
        code="PX3-CLOUD-EST-07",
        slug="07_olho_fechado",
        template=tpl_close_bracket,
        kicker="Filtro de qualidade",
        headline_html='OLHO FECHADO?<br><span class="hl">FORA.</span>',
        sub_html='Boca torta, foto borrada, piscada no clique.<br>A IA <strong>remove na triagem</strong>, você não perde tempo.',
        pill_text="QA REJECTED",
        tag_text="",
        cta_text=CTA_PRIMEIROS,
        headline_size=140,
        grid_class="lines-h",
        img_pos="50% 15%",
    ),

    # 08 — Vizinhança — hero vertical
    Spec(
        code="PX3-CLOUD-EST-08",
        slug="08_vizinhanca",
        template=tpl_hero_vertical,
        kicker="Identificação por contexto",
        headline_html='SEM FACE?<br>AINDA ASSIM,<br><span class="hl">IDENTIFICADO.</span>',
        sub_html='Costas, chapéu, mão na frente.<br>A IA usa a <strong>sequência da fila</strong> pra entregar a foto certa.',
        pill_text="CONTEXT MATCH",
        tag_text="",
        cta_text=CTA_LISTA_ESPERA,
        headline_size=130,
        grid_class="",
        img_pos="50% 22%",
    ),

    # 09 — Similaridade — diagonal
    Spec(
        code="PX3-CLOUD-EST-09",
        slug="09_similares",
        template=tpl_diagonal,
        kicker="Descarte por similaridade",
        headline_html='FOTOS IGUAIS?<br><span class="hl">SÓ A MELHOR FICA.</span>',
        sub_html='A IA compara a <strong>rajada inteira</strong> e mantém só o frame perfeito.<br>Entrega enxuta. Cliente mais feliz.',
        pill_text="BEST FRAME",
        tag_text="DEDUP · ON",
        cta_text=CTA_VER_ANTES,
        headline_size=102,
        grid_class="dots",
        img_pos="50% 20%",
    ),

    # 10 — Revisão de fundos — split right (variação de pill/tag)
    Spec(
        code="PX3-CLOUD-EST-10",
        slug="10_revisao_fundos",
        template=tpl_split_right,
        kicker="Revisão de fundos em massa",
        headline_html='REVISÃO<br>DE FUNDOS.<br><span class="hl">UM CLIQUE.</span>',
        sub_html='Pano azul, croma, estúdio móvel.<br>A IA <strong>revisa, isola e padroniza</strong> em lote.',
        pill_text="BG CLEAN · OK",
        tag_text="BATCH · 320",
        cta_text=CTA_PRIMEIROS,
        headline_size=116,
        grid_class="crosshair",
        img_pos="50% 22%",
    ),

    # 11 — Multiplataforma — text top + faixa
    Spec(
        code="PX3-CLOUD-EST-11",
        slug="11_windows_mac",
        template=tpl_text_top,
        kicker="Rodando onde você já trabalha",
        headline_html='WINDOWS OU MAC.<br><span class="hl">VOCÊ ESCOLHE.</span>',
        sub_html='Nuvem no coração, app nativo no seu PC.<br><strong>Sem forçar troca de máquina.</strong>',
        pill_text="MULTIPLATAFORMA",
        tag_text="OS · WIN · MAC",
        cta_text=CTA_LISTA_ESPERA,
        headline_size=130,
        grid_class="dots",
        img_pos="50% 20%",
    ),

    # 12 — Integração — split left (fecha com assinatura técnica)
    Spec(
        code="PX3-CLOUD-EST-12",
        slug="12_integracao_api",
        template=tpl_split_left,
        kicker="Integra com o seu sistema",
        headline_html='CONECTA COM<br>O SEU<br><span class="hl">SISTEMA.</span>',
        sub_html='API aberta pra <strong>e-commerce, ERP e galeria</strong>.<br>O Cloud PhotoRF 2.0 encaixa no fluxo que você já tem.',
        pill_text="API · READY",
        tag_text="ENDPOINT · OK",
        cta_text=CTA_PRIMEIROS,
        headline_size=118,
        grid_class="lines-h",
        img_pos="50% 20%",
    ),
]


# =============================================================================
# Render
# =============================================================================

def render_all():
    outputs: list[Path] = []
    with sync_playwright() as p:
        browser = p.chromium.launch()
        for spec in SPECS:
            folder = BASE / spec.slug
            folder.mkdir(parents=True, exist_ok=True)
            out_png = folder / f"{spec.slug}.png"

            html = spec.template(
                kicker=spec.kicker,
                headline_html=spec.headline_html,
                sub_html=spec.sub_html,
                pill_text=spec.pill_text,
                tag_text=spec.tag_text,
                cta_text=spec.cta_text,
                headline_size=spec.headline_size,
                grid_class=spec.grid_class,
                img_pos=spec.img_pos,
                rx=spec.rx,
                ry=spec.ry,
            )

            page = browser.new_page(viewport={"width": 1080, "height": 1080}, device_scale_factor=2)
            page.set_content(html, wait_until="networkidle")
            page.wait_for_timeout(400)
            page.screenshot(path=str(out_png), clip={"x": 0, "y": 0, "width": 1080, "height": 1080}, omit_background=False)
            page.close()

            img = Image.open(out_png)
            if img.size != (1080, 1080):
                img = img.resize((1080, 1080), Image.LANCZOS)
                img.save(out_png, "PNG", optimize=True)
            else:
                img.save(out_png, "PNG", optimize=True)

            size_kb = out_png.stat().st_size // 1024
            print(f"[OK] {spec.code} → {out_png} · CTA: {spec.cta_text} ({size_kb} KB)")
            outputs.append(out_png)

        browser.close()
    return outputs


if __name__ == "__main__":
    paths = render_all()
    print(f"\n[DONE] {len(paths)} criativos gerados em {BASE}")
