---
name: comfyui_build_card_art_workflow
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: pure
signature: "def comfyui_build_card_art_workflow(subject: str, *, card_style: str = \"fantasy trading card art\", checkpoint: str = \"IMG_juggernaut_xl_v11.safetensors\", width: int = 512, height: int = 768, hires: bool = True, seed: int = 0, lora: str | None = None, lora_strength: float = 1.0, negative: str | None = None, steps: int = 28, cfg: float = 7.0, sampler_name: str = \"dpmpp_2m\", scheduler: str = \"karras\", upscale_by: float = 1.5, hires_denoise: float = 0.4, upscale_model: str = \"4x_foolhardy_Remacri.pth\", filename_prefix: str = \"card_art\") -> dict"
description: "Construye el dict (API format) del workflow de UN arte de carta coleccionable (TCG) 2D: ilustracion central de una criatura/personaje/hechizo en formato vertical de carta (~512x768), composicion centrada y dramatica, dejando aire para que el motor/post anada marco/titulo/stats. Genera SOLO la ilustracion (el chrome de la carta NO). Compone comfyui_build_hires_fix_workflow (si hires) o comfyui_build_txt2img_workflow + comfyui_inject_lora (estilo opcional). Hermano de comfyui_build_portrait_avatar/item_icon/ui_hud_workflow. Pura, sin red ni I/O. class_types verificados contra /object_info (8GB lowvram)."
tags: [comfyui, ml, gamedev-2d, card, tcg, trading-card, illustration, workflow]
uses_functions: [comfyui_build_txt2img_workflow_py_ml, comfyui_build_hires_fix_workflow_py_ml, comfyui_inject_lora_py_ml]
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params:
  - name: subject
    desc: "Descripcion de la figura central de la carta (ej. 'a fire dragon breathing flames', 'an elven archer drawing a glowing bow', 'a frost elemental made of ice'). Se inserta en un prompt scaffold de carta. No puede estar vacio."
  - name: card_style
    desc: "Descriptor de estilo de la ilustracion que mantiene coherentes las cartas de un set (ej. 'fantasy trading card art', 'anime trading card art', 'realistic painted card art', 'dark gothic card art'). Pasa el MISMO card_style + checkpoint + lora a todas las cartas del set para coherencia visual. keyword-only."
  - name: checkpoint
    desc: "Checkpoint del servidor. 'IMG_juggernaut_xl_v11.safetensors' (SDXL, mejor detalle) por defecto; en 8GB lowvram con hires puede ser pesado: usa 'IMG_dreamshaper_8.safetensors' (SD1.5) y/o hires=False si la GPU se queda corta. keyword-only."
  - name: width
    desc: "Ancho del lienzo en px. Vertical de carta -> width < height. 512 por defecto. keyword-only."
  - name: height
    desc: "Alto del lienzo en px. 768 por defecto (retrato de carta). Para SDXL nativo, 768x1152 luce mejor. keyword-only."
  - name: hires
    desc: "Si True encadena la 2a pasada de detalle (UltimateSDUpscale + Remacri, re-difusion por tiles) sobre la base vertical (full art mas detallado). False deja la imagen tal cual sale del VAEDecode. keyword-only."
  - name: seed
    desc: "Semilla del KSampler (y de la pasada hires). Misma seed + mismo subject -> misma ilustracion. keyword-only."
  - name: lora
    desc: "LoRA de estilo opcional en models/loras (ej. 'SD15_detail_tweaker.safetensors', 'SDXL_anime_style.safetensors'). None = sin LoRA. Encadena estilo coherente entre cartas. keyword-only."
  - name: lora_strength
    desc: "Fuerza del LoRA sobre model y clip. Se clampa a [0.0, 2.0]. keyword-only."
  - name: negative
    desc: "Prompt negativo. None usa el negativo por defecto pensado para arte de carta (figura limpia, sin marco/borde/titulo/stats/texto/UI). keyword-only."
  - name: steps
    desc: "Pasos del KSampler (y de la pasada hires). keyword-only."
  - name: cfg
    desc: "CFG del KSampler (y de la pasada hires). keyword-only."
  - name: sampler_name
    desc: "Sampler del KSampler. keyword-only."
  - name: scheduler
    desc: "Scheduler del KSampler. keyword-only."
  - name: upscale_by
    desc: "Factor de ampliacion de la pasada hires sobre la base (1.5 -> 512x768 pasa a 768x1152). Solo si hires=True. keyword-only."
  - name: hires_denoise
    desc: "Fuerza de re-difusion de la pasada hires (0.4 por defecto: anade detalle sin alterar la composicion). Solo si hires=True. keyword-only."
  - name: upscale_model
    desc: "Modelo de upscale en models/upscale_models/ que usa la pasada hires ('4x_foolhardy_Remacri.pth'). Solo si hires=True. keyword-only."
  - name: filename_prefix
    desc: "Prefijo del PNG en output/. keyword-only."
output: "dict en API format listo para comfyui_submit_workflow: base vertical (hires-fix si hires, txt2img si no) con prompt scaffold de carta ('{subject}, {card_style}, dramatic lighting, detailed illustration, centered composition, full art, vertical card illustration, ...') + LoRA de estilo opcional. UNA carta; set coherente -> llamar por subject con mismo card_style/checkpoint/lora. El marco/titulo/stats los pone el motor/post, no este workflow."
tested: true
tests: ["golden hires: clases CheckpointLoaderSimple/KSampler/VAEDecode/UltimateSDUpscale/UpscaleModelLoader/SaveImage; subject + 'fantasy trading card art' + 'centered composition' + 'full art' + 'dramatic lighting' en prompt; base vertical 512x768 (width<height)", "edge hires=False: sin UltimateSDUpscale/UpscaleModelLoader, SaveImage <- VAEDecode", "edge dims: width=768/height=1152 reflejados, sigue vertical", "edge card_style en prompt", "edge lora: LoraLoader con strength, KSampler.model <- LoraLoader", "edge lora_strength clamp a [0,2]", "error subject vacio -> ValueError", "determinismo"]
test_file_path: "python/functions/ml/comfyui_build_card_art_workflow_test.py"
file_path: "python/functions/ml/comfyui_build_card_art_workflow.py"
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_build_card_art_workflow import comfyui_build_card_art_workflow

# Arte de carta de un dragon de fuego, formato vertical, con detalle hires, listo para submit.
# En 8GB lowvram va holgado con SD1.5 (IMG_dreamshaper_8); SDXL+hires es mas pesado.
wf = comfyui_build_card_art_workflow(
    "a fire dragon breathing flames",
    card_style="fantasy trading card art",
    checkpoint="IMG_dreamshaper_8.safetensors",
    hires=True,
    seed=7,
)
# Set coherente: misma firma de estilo para cada carta, varia solo subject.
#   for s in ["a fire dragon breathing flames", "an elven archer", "a frost elemental"]:
#       wf = comfyui_build_card_art_workflow(s, card_style="fantasy trading card art",
#                                            checkpoint="IMG_dreamshaper_8.safetensors", seed=7)
#       comfyui_submit_workflow(wf)  # -> comfyui_wait_result -> comfyui_fetch_output_image
# El marco/titulo/stats los compone el motor de juego sobre la ilustracion resultante.
```

O lanzable directo con: `./fn run comfyui_build_card_art_workflow` (imprime nodos + class_types del ejemplo).

## Cuando usarla

Cuando necesites la ILUSTRACION central de una carta coleccionable (TCG/CCG estilo
Magic/Hearthstone/Yu-Gi-Oh): una criatura, personaje o hechizo en formato vertical
de carta, composicion centrada y dramatica. Pasa el MISMO `card_style` +
`checkpoint` + (`lora`) a todas las cartas del set para que combinen visualmente;
varia solo `subject`. Usa `hires=True` para "full art" detallado; `hires=False` para
iterar rapido. El marco, el titulo y los stats los pone el motor de juego o un paso
de post sobre la ilustracion — este builder NO los pinta.

## Gotchas

- **Genera SOLO la ilustracion, no el chrome de la carta**: el marco decorativo, la
  barra de titulo, el cuadro de texto y los stats (ataque/defensa/coste) son
  composicion del motor/post. El prompt scaffold empuja a "full art illustration" y
  el negativo por defecto rechaza "card frame / border / text / stats / UI". Si
  quieres el marco horneado en la imagen, pasa un `negative` propio sin esos terminos
  y describe el marco en `subject`/`card_style` (no recomendado: el motor compone mejor).
- **Formato vertical = `width < height`**: una carta es mas alta que ancha. 512x768
  (SD1.5) o 768x1152 (SDXL nativo). Si pones width>=height pierdes el encuadre de carta.
- **SDXL + hires es pesado en 8GB lowvram**: el default `IMG_juggernaut_xl_v11` con
  `hires=True` re-difunde por tiles y puede dar OOM o ir muy lento. Si la GPU se queda
  corta: baja a `checkpoint="IMG_dreamshaper_8.safetensors"` (SD1.5), pon `hires=False`, o
  reduce `width/height`. Probado e2e en GPU con SD1.5 + hires (ver report 0153).
- **hires requiere UltimateSDUpscale + Remacri**: si el server responde HTTP 400
  "node type not found: UltimateSDUpscale", falta el custom node; usa `hires=False`.
  El `upscale_model` ('4x_foolhardy_Remacri.pth') debe existir en `models/upscale_models/`.
- **Coherencia del set = mismos parametros**: si cambias `card_style`/`checkpoint`/
  `lora`/`seed` entre cartas, el set deja de combinar. Fija esos y varia solo `subject`.
- `hires_denoise` alto (>0.6) en la 2a pasada puede deformar la figura; 0.3-0.45 anade
  detalle sin alterar la composicion.
- Es una funcion **pura**: solo arma el dict. La generacion real (GPU) la hacen
  `comfyui_submit_workflow` + `comfyui_wait_result` + `comfyui_fetch_output_image`.
