
    i 5                    R   d Z ddlmZ ddlZddlZddlZddlmZ ddlZddl	m
Z
 ddlmZmZmZ ej                  j!                  d e ee      j&                               ddlZeZdZdZd	Zed
z  Zedz  Zedz  Zedz  ZdZdZdZdZ dZ!ddZ"ddZ#ddZ$ddZ%e&dk(  r e%        yy)u+  Meta 캐러셀 광고 Venus A-1 (Hook 슬라이드) 하이브리드 이미지 생성.

Gemini API로 배경(어두운 야간 작업 환경) 생성 →
Playwright HTML 오버레이로 한글 카피 합성.
출력: 1080x1080 PNG → /home/jay/workspace/output/meta-ads/a-group-venus/venus-A1-hook.png
    )annotationsN)Path)sync_playwright)WORKSPACE_ROOTFONT_DIR
CTA_MIN_PXX   gzG?gQ?zoutput/meta-ads/a-group-venusz_bg_venus_a1_hook.jpgzvenus-A1-hook.pngz_venus_a1_hook_template.htmlu  Cinematic still photograph for a premium Meta advertisement. Scene: A dimly lit office desk late at night, viewed from slightly above at 25-degree angle. A silhouette of a person's upper body sits hunched at the desk — only the outline visible, no face details, viewed from behind or side. Scattered papers, notebooks, and a closed laptop on the dark desk surface. A single dim desk lamp casts a cold, lonely blue-grey glow — not warm, cold light only. The room is otherwise in near-darkness, deep charcoal walls. Mood: crushing weight of daily grind, invisible exhaustion, numbness, late-night loneliness. Color palette: deep charcoal (#1A1A2E), dark navy (#16213E), cold blue-grey (#0F3460). Zero warm tones — no orange, no yellow. Pure cold darkness. The bottom 40% of frame fades into absolute near-black for text overlay space. Shallow depth of field, cinematic grain (ISO 6400 film look). Shot on ARRI Alexa 65 with Zeiss Master Prime 35mm — cinematic anamorphic lens flare faint. Style: Christopher Nolan / Denis Villeneuve film still. Premium advertising photography. 1:1 square composition 1080x1080. No text, no watermarks, no logos.zgemini-3.1-flash-image-previewzgemini-3-pro-image-previewz0https://generativelanguage.googleapis.com/v1betaz3https://www.googleapis.com/auth/generative-languagec            	        t         j                         rt        dt                 t         S t        d       t        j                         } t        dt        |        d       t         dt         d}d|  dd	}d
dt        igigdddgid}t        dt         d       t        j                         }t        j                  |||d      }|j                  dv rHt        d|j                   dt                t         dt         d}t        j                  |||d      }|j                          t        j                         |z
  }|j                         }|j!                  dg       }|st#        dt%        |      dd        |d   j!                  di       j!                  d
g       }	t'        d |	D        d      }
|
5|	D cg c]  }d|v s|j!                  dd       }}t#        d|dd        |
d    j!                  d!d"      }t)        j*                  |
d    d#         }d$|v rd%nd&}t         j-                  |      }|j/                  |       t        d'|j0                   d(t        |      d)d*|d+d,       |S c c}w )-uG   Gemini API로 배경 이미지를 생성하고 JPEG로 저장합니다.u,   [배경] 캐시된 배경 이미지 사용: u(   [배경] Gemini API 토큰 획득 중...u   [배경] 토큰 획득 완료 (z chars)z/models/z:generateContentzBearer zapplication/json)AuthorizationzContent-TypepartstextresponseModalitiesIMAGETEXT)contentsgenerationConfigu1   [배경] 이미지 생성 요청 중... (모델: )i,  )headersjsontimeout)i  i  u$   [배경] 모델 접근 불가 (HTTP z). Fallback: 
candidatesu   candidates 없음: Nr   contentc              3  *   K   | ]  }d |v s|  yw)
inlineDataN ).0ps     U/home/jay/workspace/.worktrees/task-2116-dev1/tools/ai-image-gen/gen_venus_a1_hook.py	<genexpr>z&generate_background.<locals>.<genexpr>k   s     =Q<1+<q=s   	 u'   이미지 데이터 없음. 텍스트:    r   mimeTypez
image/jpegdatajpegz.jpgz.pngu   [배경] 완료:  (,z bytes, z.1fu   초))BG_JPEGexistsprintgcloud_authget_access_tokenlenGEMINI_API_BASEMODEL_ID	BG_PROMPTtimerequestspoststatus_codeFALLBACK_MODEL_IDraise_for_statusr   getRuntimeErrorstrnextbase64	b64decodewith_suffixwrite_bytesname)tokenurlr   payloadstartrespelapsedr#   r   r   
image_partr   textsmimeimage_bytesext	save_paths                    r   generate_backgroundrK   D   s   ~~<WIFG	
45((*E	+CJ<w
?@XhZ/?
@C"5'**G
  34561GV3DEG
 
=hZq
IJIIKE==gGSID :%4T5E5E4FmTeSfgh !*;)<<LM}}S'MiikE!G99;D,+J0T4C0ABCCqMi,00"=E=%=tDJ,1AqVq[vr"AADU2AYKPQQl#''
LAD"":l#;F#CDKdN&C##C(I+&	inn-RK0@/C8GTW=X\
]^ Bs   	JJc                    dt          dt          dt          dt          dt          d|  dt         dt         d	t         d
t         dt         dS )uA   Venus A-1 Hook 슬라이드 HTML 오버레이를 빌드합니다.z<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {
    font-family: 'Pretendard';
    src: url('file://z/Pretendard-Black.otf') format('opentype');
    font-weight: 900;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file://z/Pretendard-ExtraBold.otf') format('opentype');
    font-weight: 800;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file://z/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file://z/Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file://u"  /Pretendard-Regular.otf') format('opentype');
    font-weight: 400;
  }

  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  body {
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #0D0F1A;
  }

  .canvas {
    width: 1080px;
    height: 1080px;
    position: relative;
    font-family: 'Pretendard', 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
    overflow: hidden;
  }

  /* ─── 배경 이미지 ─── */
  .bg {
    position: absolute;
    inset: 0;
    background: url('file://u  ') center center / cover no-repeat;
  }

  /* ─── 전체 어둠 오버레이 (분위기 강화) ─── */
  .overlay-dark {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(10, 12, 24, 0.72) 0%,
      rgba(10, 12, 24, 0.40) 25%,
      rgba(10, 12, 24, 0.30) 45%,
      rgba(6, 8, 18, 0.65) 65%,
      rgba(3, 4, 12, 0.96) 100%
    );
  }

  /* ─── 헤드라인 (중앙 배치, 골든비율 위치) ─── */
  .headline-wrap {
    position: absolute;
    top: 50%;
    left: 64px;
    right: 64px;
    transform: translateY(-55%);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .headline {
    font-size: z?px;
    font-weight: 900;
    color: #FFFFFF;
    line-height: u  ;
    letter-spacing: -3.5px;
    word-break: keep-all;
    text-shadow:
      0 2px 32px rgba(0,0,0,0.80),
      0 0 80px rgba(0,0,0,0.50);
    /* WCAG AAA 7:1 contrast: white on dark overlay */
  }

  /* ─── 하단 텍스트 영역 ─── */
  .bottom-zone {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 380px;
  }

  /* 하단 그라디언트 오버레이 — 텍스트 가독성 WCAG AAA */
  .bottom-gradient {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(3, 4, 12, 0.0) 0%,
      rgba(3, 4, 12, 0.88) 35%,
      rgba(3, 4, 12, 0.97) 100%
    );
  }

  .subcopy-wrap {
    position: absolute;
    bottom: 100px;
    left: 64px;
    right: 112px;
  }

  .subcopy {
    font-size: zQpx;
    font-weight: 400;
    color: rgba(190, 195, 215, 0.82);
    line-height: uU  ;
    letter-spacing: -0.8px;
    word-break: keep-all;
    text-shadow: 0 1px 12px rgba(0,0,0,0.80);
  }

  .subcopy .em {
    color: rgba(220, 224, 238, 0.95);
    font-weight: 600;
  }

  /* ─── 페이지 인디케이터 1/5 ─── */
  .page-indicator {
    position: absolute;
    bottom: 44px;
    right: 52px;
    font-size: u  px;
    font-weight: 500;
    color: rgba(180, 185, 205, 0.65);
    letter-spacing: 1px;
    text-shadow: 0 1px 8px rgba(0,0,0,0.70);
    font-variant-numeric: tabular-nums;
  }

</style>
</head>
<body>
<div class="canvas">

  <!-- 배경 이미지 -->
  <div class="bg"></div>

  <!-- 전체 어둠 오버레이 -->
  <div class="overlay-dark"></div>

  <!-- 헤드라인 (중앙) -->
  <div class="headline-wrap">
    <div class="headline">
      열심히 했다.<br>
      근데 왜 나만 안 되지?
    </div>
  </div>

  <!-- 하단 서브카피 영역 -->
  <div class="bottom-zone">
    <div class="bottom-gradient"></div>
    <div class="subcopy-wrap">
      <p class="subcopy">
        <span class="em">방문 횟수, 전화 통화, 상담 건수</span>—<br>
        숫자는 쌓이는데 통장은 그대로다.
      </p>
    </div>
  </div>

  <!-- 페이지 인디케이터 -->
  <div class="page-indicator">1/5</div>

</div>
</body>
</html>)r   
_SIZE_88PX_LH_1_18_CTA_PX_LH_1_72)bg_paths    r   
build_htmlrR      s     Z  
 Z  
 Z  
 Z  
 Z  : %I &> |   &L y     y +g~ ~    c                   t        t        | j                                     }t        j	                  |d       t        dt                t        d       t               5 }|j                  j                         }	 |j                  ddd      }|j                  dt        j                          d	
       |j                  d       t        j                  j                  dd       |j                  t        t              d       |j!                          	 ddd       t        j#                         j$                  }t        dt         d|dd       y# |j!                          w xY w# 1 sw Y   TxY w)uN   HTML 오버레이를 Playwright로 캡처하여 최종 PNG를 저장합니다.zutf-8)encodingu&   [오버레이] HTML 템플릿 저장: u*   [오버레이] Playwright 캡처 시작...i8  )widthheight)viewportzfile://networkidle)
wait_untili	  Tparentsexist_okpng)pathtypeNu   [오버레이] 완료: r%   r&   z bytes))rR   r8   resolve	HTML_TEMP
write_textr)   r   chromiumlaunchnew_pagegotowait_for_timeout
OUTPUT_PNGparentmkdir
screenshotclosestatst_size)rQ   html_contentr   browserpagesizes         r   capture_overlayrt   G  s0   c'//"345L8	29+
>?	
67		 
a**##%	##tt-L#MDII	 1 1 345-IP!!$'##D4#@OOZuO=MMO
 ??$$D	#J<r$q
AB MMO
 
s%   !E0=BEE0E--E00E9c                 n   t        d       t        d       t        dt                t        d       t        j                  dd       t	               } t        |        t        d       t        dt                t        j                         j                  }t        d|d	d
       t        d       y )Nz<============================================================u5   Venus Meta 캐러셀 A-1 Hook 이미지 생성 시작u   출력: Tr[   z=
============================================================u   완료: u   파일 크기: r&   z bytes)r)   ri   
OUTPUT_DIRrk   rK   rt   rn   ro   )rQ   	file_sizes     r   mainrx   c  s    	(O	
AB	HZL
!"	(OTD1 "#G G	/	HZL
!"!))I	OIa=
/0	(OrS   __main__)returnr   )rQ   r8   rz   r8   )rQ   r   rz   None)rz   r{   )'__doc__
__future__r   r:   sysr0   pathlibr   r1   playwright.sync_apir   
gen_configr   r   r   r_   insertr8   __file__rj   r*   rO   rM   rN   rP   rv   r'   ri   rb   r/   r.   r4   r-   GEMINI_SCOPErK   rR   rt   rx   __name__r   rS   r   <module>r      s    #  
    / ; ; 3tH~,,- . 

 ==

.
.--
77	J 
, ,0 DD3v@PC8* zF rS   