
    (<i=              
          d 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de
 ZeZdZdZd	Zd
ZdZdZdZdZe	dz  Zedz  Zedz  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edz  fdZ(dedede)fdZ*d ed!ed"e+d#e+de)f
d$Z,d% Z-e.d&k(  r e-        yy)'u   Cell-5 GA × 관리자/조직 비전 배너 — 2장 생성
  1. meta-feed-1080x1080.png  (정사각형)
  2. google-resp-1200x628.png (가로형)

Cell-4 GA 브랜드 다크 레드 시스템 기반.
    N)Path)sync_playwright)WORKSPACE_ROOTFONT_DIR
CTA_MIN_PXfile://*   ,   .   >   D   gQ?g?   zoutput/banners/cell-5-ga-leaderzmeta-feed-1080x1080.pngzgoogle-resp-1200x628.pngzmeta-feed-1080x1080.htmlzgoogle-resp-1200x628.htmlzbg-cell5-1080.pngzbg-cell5-1200.pngz0https://generativelanguage.googleapis.com/v1betaa  Dark moody cafe interior, empty chairs around a small table, open laptop with glowing screen, single warm light source from above, contemplative atmosphere, dark tones with warm highlights, corporate meeting space feeling, no people, cinematic lighting, ultra-realistic photographa  Wide angle view of dark modern meeting room, long table with empty chairs, city lights visible through window on right side, warm desk lamp on table, lonely professional atmosphere, dark ambient with warm accents, no people, ultra-realistic photograph, landscape formatu  <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-Black.otf') format('opentype'); font-weight: 900; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-ExtraBold.otf') format('opentype'); font-weight: 800; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-Bold.otf') format('opentype'); font-weight: 700; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-SemiBold.otf') format('opentype'); font-weight: 600; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-Regular.otf') format('opentype'); font-weight: 400; }}

  * {{ margin: 0; padding: 0; box-sizing: border-box; }}
  body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #0D0D0D;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
  }}
  .container {{
    position: relative;
    width: 1080px;
    height: 1080px;
    overflow: hidden;
  }}

  /* 배경 이미지 */
  .bg {{
    position: absolute;
    inset: 0;
    background-image: url('{bg_path}');
    background-size: cover;
    background-position: center;
  }}

  /* 다크 오버레이 */
  .overlay-dark {{
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,0.48);
  }}

  /* 레드 글로우 */
  .overlay-glow {{
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse 70% 55% at 50% 50%, rgba(239,59,36,0.18) 0%, transparent 70%);
  }}

  /* 중앙 다크 패널 */
  .panel {{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 860px;
    padding: 60px 52px;
    border-radius: 12px;
    background: rgba(13,13,13,0.82);
    backdrop-filter: blur(4px);
    display: flex;
    flex-direction: column;
    gap: 0;
  }}

  /* 뱃지 */
  .badge {{
    display: inline-flex;
    align-items: center;
    height: 52px;
    padding: 0 24px;
    background: #EF3B24;
    border-radius: 6px;
    font-size: {_CTA_PX}px;
    font-weight: 700;
    color: #FFFFFF;
    letter-spacing: -0.02em;
    white-space: nowrap;
    width: fit-content;
    margin-bottom: 28px;
  }}

  /* 헤드라인 */
  .headline {{
    font-size: {_SIZE_68PX}px;
    font-weight: 800;
    color: #FFFFFF;
    line-height: {_LH_1_22};
    letter-spacing: -0.03em;
    word-break: keep-all;
    margin-bottom: 20px;
  }}
  .headline .red {{ color: #EF3B24; }}

  /* date-tag / urgency */
  .date-tag {{
    font-size: {_SIZE_42PX}px;
    font-weight: 700;
    color: rgba(239,59,36,0.85);
    letter-spacing: -0.02em;
    white-space: nowrap;
    margin-bottom: 18px;
  }}

  /* 구분자 */
  .divider {{
    width: 100%;
    height: 1px;
    background: rgba(239,59,36,0.7);
    margin: 22px 0;
  }}

  /* 서브카피 */
  .sub {{
    font-size: {_SIZE_46PX}px;
    font-weight: 600;
    color: rgba(255,255,255,0.90);
    line-height: {_LH_1_35};
    letter-spacing: -0.02em;
    word-break: keep-all;
    margin-bottom: 32px;
  }}

  /* CTA */
  .cta {{
    display: inline-flex;
    align-items: center;
    height: auto;
    padding: 22px 48px;
    background: #EF3B24;
    border-radius: 8px;
    font-size: {_SIZE_46PX}px;
    font-weight: 700;
    color: #FFFFFF;
    letter-spacing: -0.02em;
    white-space: nowrap;
    width: fit-content;
  }}
</style>
</head>
<body>
<div class="container">
  <div class="bg"></div>
  <div class="overlay-dark"></div>
  <div class="overlay-glow"></div>

  <div class="panel">
    <div class="badge">보험설계사 이직 가이드</div>
    <div class="headline">GA 지점장, <span class="red">혼자</span> 시작 안 해도 됩니다</div>
    <div class="date-tag">1200% 룰 시행 전 지점장 전환이 유리한 이유</div>
    <div class="divider"></div>
    <div class="sub">조직 구축 시 사무실 개설비 지원</div>
    <div class="cta">지점장 비전 상담 신청 →</div>
  </div>
</div>
</body>
</html>
u0  <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-Black.otf') format('opentype'); font-weight: 900; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-ExtraBold.otf') format('opentype'); font-weight: 800; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-Bold.otf') format('opentype'); font-weight: 700; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-SemiBold.otf') format('opentype'); font-weight: 600; }}
  @font-face {{ font-family: 'Pretendard'; src: url('{font_dir}/Pretendard-Regular.otf') format('opentype'); font-weight: 400; }}

  * {{ margin: 0; padding: 0; box-sizing: border-box; }}
  body {{
    width: 1200px;
    height: 628px;
    overflow: hidden;
    background: #0D0D0D;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
  }}
  .container {{
    position: relative;
    width: 1200px;
    height: 628px;
    overflow: hidden;
  }}

  /* 전체 배경 이미지 */
  .bg {{
    position: absolute;
    inset: 0;
    background-image: url('{bg_path}');
    background-size: cover;
    background-position: center right;
  }}

  /* 좌→우 다크 그라데이션 */
  .overlay-grad {{
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to right,
      rgba(13,13,13,0.92) 0%,
      rgba(13,13,13,0.80) 55%,
      rgba(13,13,13,0.30) 80%,
      rgba(13,13,13,0.05) 100%
    );
  }}

  /* 레드 글로우 (좌측 집중) */
  .overlay-glow {{
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse 60% 80% at 30% 50%, rgba(239,59,36,0.16) 0%, transparent 70%);
  }}

  /* 좌측 콘텐츠 영역 */
  .left {{
    position: absolute;
    top: 0;
    left: 0;
    width: 760px;
    height: 100%;
    display: flex;
    flex-direction: row;
    align-items: stretch;
  }}

  /* 레드 세로 액센트바 */
  .accent-bar {{
    width: 4px;
    background: #EF3B24;
    margin: 60px 0;
    border-radius: 2px;
    flex-shrink: 0;
  }}

  /* 텍스트 스택 */
  .text-stack {{
    padding-left: 28px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 20px;
  }}

  /* 뱃지 */
  .badge {{
    display: inline-flex;
    align-items: center;
    height: 48px;
    padding: 0 20px;
    background: #EF3B24;
    border-radius: 6px;
    font-size: {_CTA_PX}px;
    font-weight: 700;
    color: #FFFFFF;
    letter-spacing: -0.02em;
    white-space: nowrap;
    width: fit-content;
  }}

  /* 헤드라인 */
  .headline {{
    font-size: {_SIZE_62PX}px;
    font-weight: 800;
    color: #FFFFFF;
    line-height: {_LH_1_22};
    letter-spacing: -0.03em;
    word-break: keep-all;
  }}
  .headline .red {{ color: #EF3B24; }}

  /* date-tag */
  .date-tag {{
    font-size: {_SIZE_42PX}px;
    font-weight: 700;
    color: rgba(239,59,36,0.85);
    letter-spacing: -0.02em;
    white-space: nowrap;
  }}

  /* 구분자 */
  .divider {{
    color: rgba(239,59,36,0.7);
    font-size: {_CTA_PX}px;
    font-weight: 400;
    line-height: {_LH_1};
  }}

  /* 서브카피 */
  .sub {{
    font-size: {_CTA_PX}px;
    font-weight: 600;
    color: rgba(255,255,255,0.90);
    letter-spacing: -0.02em;
    word-break: keep-all;
  }}

  /* CTA */
  .cta {{
    display: inline-flex;
    align-items: center;
    padding: 20px 44px;
    background: #EF3B24;
    border-radius: 8px;
    font-size: {_SIZE_44PX}px;
    font-weight: 700;
    color: #FFFFFF;
    letter-spacing: -0.02em;
    white-space: nowrap;
    width: fit-content;
  }}
</style>
</head>
<body>
<div class="container">
  <div class="bg"></div>
  <div class="overlay-grad"></div>
  <div class="overlay-glow"></div>

  <div class="left">
    <div class="accent-bar"></div>
    <div class="text-stack">
      <div class="badge">보험설계사 이직 가이드</div>
      <div class="headline">GA 지점장, <span class="red">혼자</span> 시작 안 해도 됩니다</div>
      <div class="date-tag">1200% 룰 시행 전 지점장 전환이 유리한 이유</div>
      <div class="divider">─────────────────────────────</div>
      <div class="sub">조직 구축 시 사무실 개설비 지원</div>
      <div class="cta">지점장 비전 상담 신청 →</div>
    </div>
  </div>
</div>
</body>
</html>
returnc                      	 t        j                  d      S # t        $ r} t        d|  d       Y d} ~ nd} ~ ww xY w	 t        j                         S # t        $ r}t        d|        Y d}~yd}~ww xY w)u!   인증 토큰을 가져옵니다.z3https://www.googleapis.com/auth/generative-languageu     [SA 토큰 오류] u    — ADC 시도Nu     [인증 실패] )gcloud_authget_service_account_token	Exceptionprintget_access_token)ee2s     _/home/jay/workspace/.worktrees/task-2057-dev2/tools/ai-image-gen/gen_cell5_ga_leader_banners.pyget_auth_tokenr     s{    :44A
 	
  :%aS899:++-- "2$'(s'    	949A 	A2A--A2promptoutput_pathc           
      \   t               }|syd| dd}g d}|D ]h  }t         d| d}dd	| igigd
ddgid}t        d| d       	 t        j                  |||d      }|j                  dk(  r|j                         }
|
j                  di g      d   j                  di       j                  dg       D ]Q  }d|v st        j                  |d   d         }|j                  |       t        d| dt        |      dd         y |
j                  di g      d   j                  dd       }t        d!|        t        d"t        |
      dd#         At        d$|j                   d%|j                  dd&         k y# t
        $ r}	t        d|	        Y d}	~	d}	~	ww xY w)'u2   Gemini API로 배경 이미지를 생성합니다.FzBearer zapplication/json)AuthorizationzContent-Type)z)gemini-2.0-flash-preview-image-generationzgemini-3.1-flash-image-previewzgemini-3-pro-image-previewz/models/z:generateContentpartstextresponseModalitiesTEXTIMAGE)contentsgenerationConfigu     요청 중... (모델: )x   )headersjsontimeoutu     [연결 오류] N   
candidatesr   content
inlineDatadatau     저장 완료:  (,z bytes)TfinishReason?u)     [이미지 파트 없음] finishReason=u
     응답: i  z  [HTTP z] i,  )r   GEMINI_API_BASEr   requestspostr   status_coder(   getbase64	b64decodewrite_byteslenstrr   )r   r   tokenr'   modelsmodelurlpayloadrespr   r.   part	img_bytesreasons                 r   generate_backgroundrF     s   E")% 1CUVGF
  D !%0@A!VV$4#567!57H I
 	)%23	==gGSQD s"99;Dt,Q/Y#Wb!	 
  4' & 0 0l1CF1K LI++I6-k]"S^A<NgVW	  XXlRD1!488MF=fXFGJs4y#/01HT--.b4C0ABC9D: )  	&qc*+	s   F			F+F&&F+	html_path
output_pngwidthheightc                    t               5 }|j                  j                         }|j                  ||d      }|j	                  d|         |j                  d       |j                  t        |      d       |j                          ddd       |j                         j                  dz  }t        d	| d
|dd       y# 1 sw Y   :xY w)u-   Playwright로 HTML을 PNG로 캡처합니다.)rI   rJ   )viewportr   i  png)pathtypeNi   u     PNG 저장: r/   z.0fz KB)T)r   chromiumlaunchnew_pagegotowait_for_timeout
screenshotr<   closestatst_sizer   )rG   rH   rI   rJ   pbrowserpagesize_kbs           r   render_htmlr]     s    		 a**##%5F)KL		GI;'(d#S_59 oo''$.G	N:,bT
:; s   BCCc                  `   t         j                  dd       t        d       t        d       t        d       t        d       t        d       t        t        t
              } | r	dt
         nd}| st        d	       t        d
       t        t        t              }|r	dt         nd}|st        d	       t        d       t        j                  t        |      }t        j                  |d       t        t        t        dd       t        d       t        j                  t        |      }t         j                  |d       t        t         t"        dd       t        d       t        dt                t        dt                t        dt                 t        dt"                y )NT)parentsexist_okzA=================================================================u2   Cell-5 GA × 관리자/조직 비전 배너 생성u+   Cell-4 GA 다크 레드 브랜드 시스템u,   
[1/4] 1080×1080 배경 이미지 생성...r    u>     [경고] 배경 생성 실패 — 다크 폴백으로 진행u+   
[2/4] 1200×628 배경 이미지 생성...u5   
[3/4] HTML 파일 작성 및 1080×1080 렌더링...)font_dirbg_pathzutf-8)encodingi8  u4   
[4/4] HTML 파일 작성 및 1200×628 렌더링...i  it  u   
완료!u     1080×1080 HTML: u     1080×1080 PNG : u     1200×628  HTML: u     1200×628  PNG : )OUT_DIRmkdirr   rF   BG_PROMPT_1080BG_1080BG_PROMPT_1200BG_1200HTML_1080_TEMPLATEformat	_FONT_URI	HTML_1080
write_textr]   OUT_1080HTML_1200_TEMPLATE	HTML_1200OUT_1200)	bg1080_ok
bg1080_url	bg1200_ok
bg1200_urlhtml_1080_contenthtml_1200_contents         r   mainrz     sp   MM$M.	(O	
>?	
78	(O 

9:#NG<I(177)$rJNO	
89#NG<I(177)$rJNO 

BC*11J 2  *W=	8T40	
AB*11J 2  *W=	8T3/	+		{
+,	z
*+		{
+,	z
*+    __main__)/__doc__r8   syspathlibr   r4   playwright.sync_apir   
gen_configr   r   r   rN   insertr<   __file__parentr   rm   _CTA_PX
_SIZE_42PX
_SIZE_44PX
_SIZE_46PX
_SIZE_62PX
_SIZE_68PX_LH_1_22_LH_1_35_LH_1re   rp   rs   rn   rr   rh   rj   r3   rg   ri   rk   rq   r   boolrF   intr]   rz   __name__ r{   r   <module>r      sg    
   / ; ; 3tH~,,- . hZ 	





	 <
<..//00	11	
'
'
'
'D! > ^ Bo dd
 ) )$ )4 )X4 T # s t (,V zF r{   