"""
draw_effects.py — Primitivas visuales para los flyers de Kings & Queens.

Todos los efectos usan la paleta oficial:
  #73C3B4  verde agua (fondo)
  #ED6D70  coral (acentos, botones)
  #596E87  azul grisáceo (texto secundario)
  #FFFFFF  blanco (cards)
  #FFE066  amarillo resaltador
  #FFF9E6  crema notebook
"""

import math
import random
from PIL import Image, ImageDraw, ImageFont


# ---------------------------------------------------------------------------
# Helpers de color
# ---------------------------------------------------------------------------

def hex_to_rgb(hex_color: str) -> tuple:
    h = hex_color.lstrip("#")
    return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))


def hex_to_rgba(hex_color: str, alpha: int = 255) -> tuple:
    r, g, b = hex_to_rgb(hex_color)
    return (r, g, b, alpha)


# ---------------------------------------------------------------------------
# Helpers de texto
# ---------------------------------------------------------------------------

def wrap_text(draw: ImageDraw.ImageDraw, text: str, font: ImageFont.FreeTypeFont, max_width: int) -> list:
    """Divide el texto en líneas que caben dentro de max_width."""
    words = text.split()
    lines = []
    current = []
    for word in words:
        test = " ".join(current + [word])
        bbox = draw.textbbox((0, 0), test, font=font)
        if bbox[2] - bbox[0] <= max_width:
            current.append(word)
        else:
            if current:
                lines.append(" ".join(current))
            current = [word]
    if current:
        lines.append(" ".join(current))
    return lines


def draw_text_centered(draw: ImageDraw.ImageDraw, text: str, font: ImageFont.FreeTypeFont,
                        color: str, canvas_w: int, y: int) -> int:
    """Dibuja texto centrado horizontalmente. Devuelve la y del borde inferior."""
    bbox = draw.textbbox((0, 0), text, font=font)
    w = bbox[2] - bbox[0]
    x = (canvas_w - w) // 2
    draw.text((x, y), text, font=font, fill=hex_to_rgb(color))
    return y + (bbox[3] - bbox[1])


def draw_text_block_centered(draw: ImageDraw.ImageDraw, lines: list, font: ImageFont.FreeTypeFont,
                              color: str, canvas_w: int, y: int, line_spacing: int = 8) -> int:
    """Dibuja bloque de líneas centradas. Devuelve la y del borde inferior."""
    for line in lines:
        bbox = draw.textbbox((0, 0), line, font=font)
        h = bbox[3] - bbox[1]
        w = bbox[2] - bbox[0]
        x = (canvas_w - w) // 2
        draw.text((x, y), line, font=font, fill=hex_to_rgb(color))
        y += h + line_spacing
    return y


def measure_text(draw: ImageDraw.ImageDraw, text: str, font: ImageFont.FreeTypeFont) -> tuple:
    """Devuelve (width, height) del texto."""
    bbox = draw.textbbox((0, 0), text, font=font)
    return bbox[2] - bbox[0], bbox[3] - bbox[1]


# ---------------------------------------------------------------------------
# Clase principal de efectos
# ---------------------------------------------------------------------------

class DrawEffects:
    """
    Encapsula img, draw y scale para no repetir parámetros en cada llamada.
    Todos los valores de posición/tamaño están en píxeles de Story (1080x1920).
    Los métodos aplican self.scale internamente.
    """

    def __init__(self, img: Image.Image, draw: ImageDraw.ImageDraw,
                 scale: float, seed: int = 20260324):
        self.img = img
        self.draw = draw
        self.scale = scale
        self.w, self.h = img.size
        self.rng = random.Random(seed)

    def s(self, px: int) -> int:
        """Aplica escala a un valor en píxeles."""
        return max(1, int(px * self.scale))

    # -----------------------------------------------------------------------
    # Fondo y estructura
    # -----------------------------------------------------------------------

    def draw_grid_background(self, bg_color: str = "#73C3B4",
                              line_color: str = "#5EADA0",
                              spacing: int = 60, line_alpha: int = 60):
        """Fondo teal con grilla sutil superpuesta."""
        self.draw.rectangle([(0, 0), (self.w, self.h)], fill=hex_to_rgb(bg_color))
        overlay = Image.new("RGBA", self.img.size, (0, 0, 0, 0))
        odraw = ImageDraw.Draw(overlay)
        r, g, b = hex_to_rgb(line_color)
        step = self.s(spacing)
        for x in range(0, self.w, step):
            odraw.line([(x, 0), (x, self.h)], fill=(r, g, b, line_alpha), width=1)
        for y in range(0, self.h, step):
            odraw.line([(0, y), (self.w, y)], fill=(r, g, b, line_alpha), width=1)
        base = self.img.convert("RGBA")
        result = Image.alpha_composite(base, overlay)
        self.img.paste(result.convert(self.img.mode))

    def draw_white_card(self, x0: int, y0: int, x1: int, y1: int,
                        radius: int = 24, shadow: bool = True):
        """Card blanca con bordes redondeados y sombra suave."""
        x0, y0, x1, y1 = self.s(x0), self.s(y0), self.s(x1), self.s(y1)
        r = self.s(radius)
        if shadow:
            shadow_layer = Image.new("RGBA", self.img.size, (0, 0, 0, 0))
            sd = ImageDraw.Draw(shadow_layer)
            off = self.s(6)
            sd.rounded_rectangle([(x0 + off, y0 + off), (x1 + off, y1 + off)],
                                  radius=r, fill=(0, 0, 0, 40))
            base = self.img.convert("RGBA")
            self.img.paste(Image.alpha_composite(base, shadow_layer).convert(self.img.mode))
        self.draw.rounded_rectangle([(x0, y0), (x1, y1)], radius=r, fill="#FFFFFF")

    def draw_cream_card(self, x0: int, y0: int, x1: int, y1: int, radius: int = 24):
        """Card crema estilo cuaderno."""
        x0, y0, x1, y1 = self.s(x0), self.s(y0), self.s(x1), self.s(y1)
        r = self.s(radius)
        self.draw.rounded_rectangle([(x0, y0), (x1, y1)], radius=r, fill="#FFF9E6")

    def draw_coral_button(self, x0: int, y0: int, x1: int, y1: int,
                          label: str, font: ImageFont.FreeTypeFont):
        """Botón CTA coral pill."""
        x0, y0, x1, y1 = self.s(x0), self.s(y0), self.s(x1), self.s(y1)
        r = self.s(50)
        self.draw.rounded_rectangle([(x0, y0), (x1, y1)], radius=r, fill="#ED6D70")
        bbox = self.draw.textbbox((0, 0), label, font=font)
        tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
        cx = (x0 + x1) // 2 - tw // 2
        cy = (y0 + y1) // 2 - th // 2
        self.draw.text((cx, cy), label, font=font, fill="#FFFFFF")

    def draw_badge_pill(self, label: str, font: ImageFont.FreeTypeFont,
                        center_x: int, y: int,
                        bg_color: str = "#ED6D70", text_color: str = "#FFFFFF") -> int:
        """Pill pequeño (badge). Devuelve la y inferior."""
        cx = self.s(center_x)
        y = self.s(y)
        bbox = self.draw.textbbox((0, 0), label, font=font)
        tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
        pad_h = self.s(20)
        pad_v = self.s(10)
        x0 = cx - tw // 2 - pad_h
        x1 = cx + tw // 2 + pad_h
        y0 = y
        y1 = y + th + pad_v * 2
        r = self.s(40)
        self.draw.rounded_rectangle([(x0, y0), (x1, y1)], radius=r, fill=bg_color)
        self.draw.text((cx - tw // 2, y0 + pad_v), label, font=font, fill=text_color)
        return y1

    # -----------------------------------------------------------------------
    # Resaltador (fibra marker)
    # -----------------------------------------------------------------------

    def draw_highlighter_stroke(self, x0: int, y0: int, x1: int, y1: int,
                                color_hex: str = "#FFE066", alpha: int = 110):
        """
        Rectángulo semi-transparente levemente rotado que simula una fibra resaltadora.
        Se dibuja ANTES del texto (llamar primero, luego dibujar el texto encima).
        """
        x0, y0, x1, y1 = self.s(x0), self.s(y0), self.s(x1), self.s(y1)
        pad_h = self.s(8)
        pad_v = self.s(3)
        x0 -= pad_h; x1 += pad_h
        y0 -= pad_v; y1 += pad_v

        r, g, b = hex_to_rgb(color_hex)
        angle = self.rng.uniform(-2, 2)

        layer = Image.new("RGBA", self.img.size, (0, 0, 0, 0))
        ldraw = ImageDraw.Draw(layer)
        ldraw.rectangle([(x0, y0), (x1, y1)], fill=(r, g, b, alpha))

        cx = (x0 + x1) / 2
        cy = (y0 + y1) / 2
        rotated = layer.rotate(angle, center=(cx, cy), expand=False)

        base = self.img.convert("RGBA")
        result = Image.alpha_composite(base, rotated)
        self.img.paste(result.convert(self.img.mode))
        # Refrescar draw tras paste
        self.draw = ImageDraw.Draw(self.img)

    def draw_highlighter_under_text(self, text: str, font: ImageFont.FreeTypeFont,
                                    center_x: int, y: int,
                                    color_hex: str = "#FFE066", alpha: int = 110):
        """Mide el texto y aplica resaltador centrado. NO dibuja el texto."""
        cx = self.s(center_x)
        y_s = self.s(y)
        bbox = self.draw.textbbox((0, 0), text, font=font)
        tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
        x0 = cx - tw // 2
        x1 = cx + tw // 2
        self.draw_highlighter_stroke(0, 0, 0, 0)  # dummy para refrescar; usar versión directa
        # Llamada directa con píxeles ya escalados:
        pad_h = self.s(8)
        pad_v = self.s(3)
        rx0 = x0 - pad_h; rx1 = x1 + pad_h
        ry0 = y_s - pad_v; ry1 = y_s + th + pad_v

        r, g, b = hex_to_rgb(color_hex)
        angle = self.rng.uniform(-2, 2)
        layer = Image.new("RGBA", self.img.size, (0, 0, 0, 0))
        ldraw = ImageDraw.Draw(layer)
        ldraw.rectangle([(rx0, ry0), (rx1, ry1)], fill=(r, g, b, alpha))
        cx_r = (rx0 + rx1) / 2
        cy_r = (ry0 + ry1) / 2
        rotated = layer.rotate(angle, center=(cx_r, cy_r), expand=False)
        base = self.img.convert("RGBA")
        result = Image.alpha_composite(base, rotated)
        self.img.paste(result.convert(self.img.mode))
        self.draw = ImageDraw.Draw(self.img)

    # -----------------------------------------------------------------------
    # Doodles
    # -----------------------------------------------------------------------

    def draw_doodle_underline(self, x0: int, y: int, x1: int,
                              color: str = "#ED6D70", thickness: int = 3, wobble: int = 3):
        """Línea ondulada simulando subrayado a mano."""
        x0, y_s, x1 = self.s(x0), self.s(y), self.s(x1)
        t = self.s(thickness)
        segments = 10
        step = (x1 - x0) / segments
        pts = [(x0 + i * step, y_s + self.rng.randint(-wobble, wobble))
               for i in range(segments + 1)]
        rgb = hex_to_rgb(color)
        for i in range(len(pts) - 1):
            self.draw.line([pts[i], pts[i + 1]], fill=rgb, width=t)

    def draw_doodle_bracket_left(self, x: int, y_top: int, y_bottom: int,
                                  color: str = "#596E87", thickness: int = 3, serif: int = 20):
        """Corchete izquierdo dibujado a mano."""
        x_s = self.s(x)
        yt = self.s(y_top) + self.rng.randint(-2, 2)
        yb = self.s(y_bottom) + self.rng.randint(-2, 2)
        sf = self.s(serif)
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        self.draw.line([(x_s, yt), (x_s, yb)], fill=rgb, width=t)
        self.draw.line([(x_s, yt), (x_s + sf, yt + self.rng.randint(-2, 2))], fill=rgb, width=t)
        self.draw.line([(x_s, yb), (x_s + sf, yb + self.rng.randint(-2, 2))], fill=rgb, width=t)

    def draw_doodle_bracket_right(self, x: int, y_top: int, y_bottom: int,
                                   color: str = "#596E87", thickness: int = 3, serif: int = 20):
        """Corchete derecho dibujado a mano."""
        x_s = self.s(x)
        yt = self.s(y_top) + self.rng.randint(-2, 2)
        yb = self.s(y_bottom) + self.rng.randint(-2, 2)
        sf = self.s(serif)
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        self.draw.line([(x_s, yt), (x_s, yb)], fill=rgb, width=t)
        self.draw.line([(x_s, yt), (x_s - sf, yt + self.rng.randint(-2, 2))], fill=rgb, width=t)
        self.draw.line([(x_s, yb), (x_s - sf, yb + self.rng.randint(-2, 2))], fill=rgb, width=t)

    def draw_doodle_squiggle(self, center_x: int, center_y: int, width: int,
                              color: str = "#ED6D70", thickness: int = 2):
        """S-curve decorativa como separador de sección."""
        cx = self.s(center_x)
        cy = self.s(center_y)
        w = self.s(width) // 2
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        pts = [
            (cx - w, cy),
            (cx - w // 2, cy - self.s(10)),
            (cx, cy),
            (cx + w // 2, cy + self.s(10)),
            (cx + w, cy),
        ]
        for i in range(len(pts) - 1):
            self.draw.line([pts[i], pts[i+1]], fill=rgb, width=t)

    def draw_doodle_arrow(self, sx: int, sy: int, ex: int, ey: int,
                          color: str = "#ED6D70", thickness: int = 3, head: int = 15):
        """Flecha simple desde (sx,sy) hasta (ex,ey)."""
        sx, sy = self.s(sx), self.s(sy)
        ex, ey = self.s(ex), self.s(ey)
        t = self.s(thickness)
        h = self.s(head)
        rgb = hex_to_rgb(color)
        self.draw.line([(sx, sy), (ex, ey)], fill=rgb, width=t)
        angle = math.atan2(ey - sy, ex - sx)
        for da in [0.5, -0.5]:
            hx = ex - int(h * math.cos(angle - da))
            hy = ey - int(h * math.sin(angle - da))
            self.draw.line([(ex, ey), (hx, hy)], fill=rgb, width=t)

    # -----------------------------------------------------------------------
    # Stickers
    # -----------------------------------------------------------------------

    def draw_star_sticker(self, cx: int, cy: int, size: int,
                          color: str = "#ED6D70", rotation: float = 0, thickness: int = 3):
        """Estrella 5 puntas, solo contorno."""
        cx, cy = self.s(cx), self.s(cy)
        outer = self.s(size)
        inner = int(outer * 0.45)
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        points = []
        for i in range(10):
            r = outer if i % 2 == 0 else inner
            angle = math.radians(rotation + i * 36 - 90)
            points.append((cx + r * math.cos(angle), cy + r * math.sin(angle)))
        self.draw.polygon(points, outline=rgb, width=t)

    def draw_planet_sticker(self, cx: int, cy: int, size: int,
                             color: str = "#73C3B4", thickness: int = 3):
        """Planeta: círculo + anillo elíptico inclinado."""
        cx, cy = self.s(cx), self.s(cy)
        r = self.s(size)
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        self.draw.ellipse([(cx - r, cy - r), (cx + r, cy + r)], outline=rgb, width=t)
        rx, ry = int(r * 1.8), int(r * 0.5)
        self.draw.ellipse([(cx - rx, cy - ry), (cx + rx, cy + ry)], outline=rgb, width=t)

    def draw_globe_sticker(self, cx: int, cy: int, size: int,
                            color: str = "#596E87", thickness: int = 3):
        """Globo terráqueo: círculo + líneas de longitud/latitud."""
        cx, cy = self.s(cx), self.s(cy)
        r = self.s(size)
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        self.draw.ellipse([(cx - r, cy - r), (cx + r, cy + r)], outline=rgb, width=t)
        rx_inner = int(r * 0.55)
        self.draw.ellipse([(cx - rx_inner, cy - r), (cx + rx_inner, cy + r)], outline=rgb, width=t)
        self.draw.line([(cx - r, cy), (cx + r, cy)], fill=rgb, width=t)

    def draw_sparkle(self, cx: int, cy: int, size: int,
                     color: str = "#FFE066", thickness: int = 2):
        """Destello 4 puntas."""
        cx, cy = self.s(cx), self.s(cy)
        r = self.s(size)
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        self.draw.line([(cx, cy - r), (cx, cy + r)], fill=rgb, width=t)
        self.draw.line([(cx - r, cy), (cx + r, cy)], fill=rgb, width=t)
        d = int(r * 0.6)
        self.draw.line([(cx - d, cy - d), (cx + d, cy + d)], fill=rgb, width=max(1, t - 1))
        self.draw.line([(cx + d, cy - d), (cx - d, cy + d)], fill=rgb, width=max(1, t - 1))

    def draw_paperclip_sticker(self, cx: int, cy: int, size: int,
                                color: str = "#596E87", thickness: int = 3):
        """Clip de papel simplificado (dos rectángulos redondeados anidados)."""
        cx, cy = self.s(cx), self.s(cy)
        w = self.s(size // 3)
        h = self.s(size)
        t = self.s(thickness)
        rgb = hex_to_rgb(color)
        r = w
        self.draw.rounded_rectangle(
            [(cx - w, cy - h // 2), (cx + w, cy + h // 2)],
            radius=r, outline=rgb, width=t
        )
        self.draw.rounded_rectangle(
            [(cx - w + t * 2, cy - h // 3), (cx + w - t * 2, cy + h // 2 - t * 2)],
            radius=max(1, r - t), outline=rgb, width=t
        )

    # -----------------------------------------------------------------------
    # Scatter de stickers
    # -----------------------------------------------------------------------

    def scatter_stickers(self, sticker_types: list, safe_zones: list,
                         min_count: int = 4, max_count: int = 8,
                         min_size: int = 30, max_size: int = 80):
        """
        Dispersa stickers evitando las safe_zones (lista de (x0,y0,x1,y1) en píxeles reales).
        Los stickers pueden aparecer en cualquier parte del canvas — el chequeo usa
        solo un padding pequeño para que puedan quedar cerca de los bordes de las cards.
        """
        count = self.rng.randint(min_count, max_count)
        attempts = 0
        placed = 0

        sticker_colors = {
            "star":      ["#ED6D70", "#FFE066"],
            "planet":    ["#73C3B4", "#ED6D70"],
            "globe":     ["#596E87"],
            "clip":      ["#596E87"],
            "sparkle":   ["#FFE066", "#ED6D70"],
        }

        while placed < count and attempts < count * 15:
            attempts += 1
            size = self.rng.randint(self.s(min_size), self.s(max_size))
            cx = self.rng.randint(size, self.w - size)
            cy = self.rng.randint(size, self.h - size)

            overlaps = False
            for (zx0, zy0, zx1, zy1) in safe_zones:
                # Padding pequeño: solo evitamos que el CENTRO del sticker caiga
                # dentro del contenido (los bordes del sticker sí pueden solapar)
                pad = self.s(10)
                if (cx > zx0 - pad and cx < zx1 + pad and
                        cy > zy0 - pad and cy < zy1 + pad):
                    overlaps = True
                    break
            if overlaps:
                continue

            stype = self.rng.choice(sticker_types)
            color_list = sticker_colors.get(stype, ["#ED6D70"])
            color = self.rng.choice(color_list)
            size_unscaled = size  # ya está escalado, pero los métodos aplican s() de nuevo
            # Llamar con valores ya en píxeles finales directamente:
            size_raw = max(20, size // max(1, int(self.scale)))

            if stype == "star":
                rot = self.rng.uniform(0, 360)
                self.draw_star_sticker(0, 0, size_raw, color, rot)
                # Re-dibujar directamente sobre coordenadas absolutas
                outer = size
                inner = int(outer * 0.45)
                rgb = hex_to_rgb(color)
                points = []
                for i in range(10):
                    r = outer if i % 2 == 0 else inner
                    angle = math.radians(rot + i * 36 - 90)
                    points.append((cx + r * math.cos(angle), cy + r * math.sin(angle)))
                self.draw.polygon(points, outline=rgb, width=max(2, self.s(3)))
            elif stype == "planet":
                rgb = hex_to_rgb(color)
                t = max(2, self.s(3))
                self.draw.ellipse([(cx - size, cy - size), (cx + size, cy + size)], outline=rgb, width=t)
                rx = int(size * 1.8)
                ry = int(size * 0.5)
                self.draw.ellipse([(cx - rx, cy - ry), (cx + rx, cy + ry)], outline=rgb, width=t)
            elif stype == "globe":
                rgb = hex_to_rgb(color)
                t = max(2, self.s(3))
                self.draw.ellipse([(cx - size, cy - size), (cx + size, cy + size)], outline=rgb, width=t)
                rx_i = int(size * 0.55)
                self.draw.ellipse([(cx - rx_i, cy - size), (cx + rx_i, cy + size)], outline=rgb, width=t)
                self.draw.line([(cx - size, cy), (cx + size, cy)], fill=rgb, width=t)
            elif stype == "sparkle":
                rgb = hex_to_rgb(color)
                t = max(1, self.s(2))
                self.draw.line([(cx, cy - size), (cx, cy + size)], fill=rgb, width=t)
                self.draw.line([(cx - size, cy), (cx + size, cy)], fill=rgb, width=t)
                d = int(size * 0.6)
                self.draw.line([(cx - d, cy - d), (cx + d, cy + d)], fill=rgb, width=max(1, t - 1))
                self.draw.line([(cx + d, cy - d), (cx - d, cy + d)], fill=rgb, width=max(1, t - 1))
            elif stype == "clip":
                rgb = hex_to_rgb(color)
                t = max(2, self.s(3))
                w_c = max(5, size // 3)
                r_c = w_c
                self.draw.rounded_rectangle(
                    [(cx - w_c, cy - size), (cx + w_c, cy + size)],
                    radius=r_c, outline=rgb, width=t)

            placed += 1

    # -----------------------------------------------------------------------
    # Logo programático
    # -----------------------------------------------------------------------

    def draw_crown(self, cx: int, cy: int, size: int):
        """
        Corona estilizada: forma tipo polígono con puntas y base teal.
        cx, cy son el centro de la corona (en coords sin escalar).
        """
        cx_px, cy_px = self.s(cx), self.s(cy)
        w = self.s(size)
        h = int(w * 0.70)
        coral = hex_to_rgb("#ED6D70")
        teal_light = (180, 225, 220)  # teal más claro para la base (visible sobre teal bg)

        top_y = cy_px - h // 2
        base_h = int(h * 0.30)
        base_y = cy_px + h // 2 - base_h

        # Cuerpo principal de la corona (polígono coral)
        crown_pts = [
            (cx_px - w // 2, base_y),
            (cx_px - w // 2, top_y + int(h * 0.45)),
            (cx_px - int(w * 0.28), top_y),
            (cx_px - int(w * 0.08), top_y + int(h * 0.38)),
            (cx_px, top_y - int(h * 0.08)),
            (cx_px + int(w * 0.08), top_y + int(h * 0.38)),
            (cx_px + int(w * 0.28), top_y),
            (cx_px + w // 2, top_y + int(h * 0.45)),
            (cx_px + w // 2, base_y),
        ]
        self.draw.polygon(crown_pts, fill=coral)

        # Base de la corona en teal claro (cintillo)
        self.draw.rectangle(
            [(cx_px - w // 2, base_y), (cx_px + w // 2, cy_px + h // 2)],
            fill=teal_light
        )

        # Puntos decorativos en el cintillo (teal oscuro)
        dot_r = max(5, int(w * 0.06))
        dot_y = base_y + base_h // 2
        dot_color = hex_to_rgb("#5EADA0")
        for dx in [-int(w * 0.28), -int(w * 0.14), 0, int(w * 0.14), int(w * 0.28)]:
            self.draw.ellipse(
                [(cx_px + dx - dot_r, dot_y - dot_r),
                 (cx_px + dx + dot_r, dot_y + dot_r)],
                fill=dot_color
            )

        # Perlas en las puntas de la corona
        tip_r = max(6, int(w * 0.07))
        for tx, ty in [
            (cx_px - int(w * 0.28), top_y),
            (cx_px, top_y - int(h * 0.08)),
            (cx_px + int(w * 0.28), top_y),
        ]:
            self.draw.ellipse(
                [(tx - tip_r, ty - tip_r), (tx + tip_r, ty + tip_r)],
                fill=coral
            )
        small_r = max(4, int(w * 0.05))
        for tx, ty in [
            (cx_px - w // 2, top_y + int(h * 0.45)),
            (cx_px + w // 2, top_y + int(h * 0.45)),
        ]:
            self.draw.ellipse(
                [(tx - small_r, ty - small_r), (tx + small_r, ty + small_r)],
                fill=coral
            )

    def draw_logo_area(self, center_x: int, top_y: int,
                       font_display: ImageFont.FreeTypeFont,
                       font_script: ImageFont.FreeTypeFont) -> int:
        """
        Dibuja corona + 'KINGS & QUEENS' + 'English Learning'.
        Devuelve la y inferior de toda la zona del logo.
        """
        cx = self.s(center_x)
        y = self.s(top_y)

        # Corona (más grande para que sea visible en el canvas)
        crown_unscaled_size = 110
        crown_h = int(self.s(crown_unscaled_size) * 0.65)
        crown_cy = top_y + int(crown_unscaled_size * 0.5)
        self.draw_crown(center_x, crown_cy, crown_unscaled_size)
        y += crown_h + self.s(12)

        # "KINGS & QUEENS" en BLANCO (sobre fondo teal)
        text_kq = "KINGS & QUEENS"
        bbox = self.draw.textbbox((0, 0), text_kq, font=font_display)
        tw = bbox[2] - bbox[0]
        self.draw.text((cx - tw // 2, y), text_kq, font=font_display, fill="#FFFFFF")
        y += bbox[3] - bbox[1] + self.s(4)

        # "English Learning" en coral
        text_el = "English Learning"
        bbox2 = self.draw.textbbox((0, 0), text_el, font=font_script)
        tw2 = bbox2[2] - bbox2[0]
        self.draw.text((cx - tw2 // 2, y), text_el, font=font_script, fill="#ED6D70")
        y += bbox2[3] - bbox2[1] + self.s(8)

        return y

    def draw_footer(self, font_body: ImageFont.FreeTypeFont,
                    whatsapp: str = "+54 9 291-4227793"):
        """Footer con WhatsApp al pie del flyer."""
        y_footer = int(self.h * 0.91)
        text = f"  {whatsapp}"

        # Fondo semitransparente
        layer = Image.new("RGBA", self.img.size, (0, 0, 0, 0))
        ldraw = ImageDraw.Draw(layer)
        ldraw.rectangle([(0, y_footer - self.s(10)), (self.w, self.h)],
                        fill=(89, 110, 135, 160))
        base = self.img.convert("RGBA")
        self.img.paste(Image.alpha_composite(base, layer).convert(self.img.mode))
        self.draw = ImageDraw.Draw(self.img)

        bbox = self.draw.textbbox((0, 0), text, font=font_body)
        tw = bbox[2] - bbox[0]
        th = bbox[3] - bbox[1]
        tx = (self.w - tw) // 2
        ty = y_footer + self.s(5)
        self.draw.text((tx, ty), text, font=font_body, fill="#FFFFFF")
