
    iF                    h   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
  ee      j                  Zej                  j                  d ee             ddlZ ed      Zedz  Zedz  Zed	z  Z ej,                         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 ddZ!e"dk(  r e!        yy)u  GA 배너 M2-1 '정당한 대우' 세트 생성 — 하이브리드 방식 (Gemini 배경 + Playwright 오버레이).

산출물:
  /home/jay/workspace/output/google-ads/banners/ga-fair-1200x628.png
  /home/jay/workspace/output/google-ads/banners/ga-fair-1080x1080.png
    )annotationsN)Path)sync_playwrightz-/home/jay/workspace/output/google-ads/bannerszga-fair-bg.jpgzga-fair-1200x628.pngzga-fair-1080x1080.pngz.local/share/fonts/Pretendarda  A top-view photo scene of a clean office desk with two documents placed side by side. One document has red marks/annotations, the other has green checkmarks. A single pen and a coffee cup are on the desk. Minimalist and analytical atmosphere. Bright, even studio lighting. High-quality photorealistic style. Neutral and professional tone. No text, no people, no logos. Clean workspace scene.z0https://generativelanguage.googleapis.com/v1betaz3https://www.googleapis.com/auth/generative-languagegemini-3.1-flash-image-previewgemini-3-pro-image-previewc                    t        d       t        j                  d      } | rJt        d       g d}|D ]5  }t        d|        	 t         d| d|  }dd	t        igigd
ddgid}t        j                  ||d      }|j                  dk(  r|j                         }|j                  dg       }|r|d   j                  di       j                  dg       }|D ]b  }	d|	v s|	d   d   }
t        j                  |
      }t        j                  |       t        dt         dt        |      dd       t        c c S  t        d| d|j                   d|j                  dd         8 t        d       	 t        j"                  t$              }t&        t(        fD ]   }	 t         d| d }d!| d"d#}dd	t        igigd
ddgid}t        j                  |||d$      }|j                  dk(  r|j                         }|j                  dg       }|r~|d   j                  di       j                  dg       }|D ]T  }	d|	v s|	d   d   }
t        j                  |
      }t        j                  |       t        d%t                t        c c S  t        d&| d|j                   d|j                  dd         # 	 t+        d(      # t         $ r}t        d| d|        Y d}~d}~ww xY w# t         $ r}t        d&| d|        Y d}~xd}~ww xY w# t         $ r"}t        d'|        Y d}~t+        d(      d}~ww xY w))u?   Gemini API로 배경 이미지를 생성하고 저장합니다.u(   [배경 생성] Gemini API 호출 중...GEMINI_API_KEYu     인증: API 키 사용)r   r   zgemini-2.5-flash-imageu     모델 시도: z/models/z:generateContent?key=partstextresponseModalitiesIMAGETEXT)contentsgenerationConfigx   )jsontimeout   
candidatesr   content
inlineDatadatau     배경 생성 완료:  (, bytes)  u    응답 z: Nu	    오류: u%     API 키 실패, SA 토큰 시도...z:generateContentzBearer zapplication/json)AuthorizationzContent-Type)headersr   r   u     배경 생성 완료 (SA): z  SA/u     SA 토큰 오류: uZ   모든 Gemini API 인증 방법 실패 — 배경 이미지를 생성할 수 없습니다.)printgcloud_authget_api_keyGEMINI_API_BASEGEMINI_BG_PROMPTrequestspoststatus_coder   getbase64	b64decodeBG_IMAGE_PATHwrite_byteslenr   	Exceptionget_service_account_tokenGEMINI_SCOPEMODEL_PRIMARYMODEL_FALLBACKRuntimeError)api_keymodels_to_trymodelurlpayloadrespr   r   r
   partimg_b64	img_bytesetokenr   s                  _/home/jay/workspace/.worktrees/task-2116-dev1/tools/ai-image-gen/_backup/gen_ga_fair_banners.pygenerate_backgroundr?   5   s   	
45 %%&67G(*

 # 	0E%eW-.0()%8MgYW")V5E,F+G!H I)=?P(Q  }}SwD##s*99;D!%,!;J! *1 1 1)R @ D DWb Q$) 5D+t3*.|*<V*D,2,<,<W,E	 - 9 9) D %(@rRUV_R`abQccj&k l'4 45 5'$*:*:);2diio=NOP+	04 

12*55lC#^4 	3E3()%8HI.5eW,=Oab")V5E,F+G!H I)=?P(Q  }}S'QTU##s*99;D!%,!;J! *1 1 1)R @ D DWb Q$) 5D+t3*.|*<V*D,2,<,<W,E	 - 9 9) D %(Em_&U V'4 45 eWHT-=-=,>b4C@QRS+	36 s
ttE  05'1#.//0:  3eWIaS1223 *$QC())
s
tt*s|   BK#AK?,K:)L $B!K7AK7L ,K7 L 	K4K//K47	L LL LL 	M
(MM
c                F    dt          dt          dt          dt          d|  dS )N<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///Pretendard-SemiBold.otf') format('opentype');
    font-weight: 600;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file://uF  /Pretendard-Regular.otf') format('opentype');
    font-weight: 400;
  }

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

  body {
    width: 1200px;
    height: 628px;
    overflow: hidden;
    background: #1A2526;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
  }

  .canvas {
    width: 1200px;
    height: 628px;
    position: relative;
    overflow: hidden;
  }

  /* 우측 40% - Gemini 배경 이미지 */
  .bg-right {
    position: absolute;
    top: 0;
    right: 0;
    width: 480px;
    height: 628px;
    background-image: url('file://u
  ');
    background-size: cover;
    background-position: center center;
  }

  /* 좌측→우측 그라데이션 오버레이 (배경 위에 덮음) */
  .gradient-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(
      to right,
      #1A2526 0%,
      #1A2526 58%,
      rgba(26, 37, 38, 0.85) 70%,
      rgba(26, 37, 38, 0.3) 82%,
      rgba(26, 37, 38, 0.0) 100%
    );
  }

  /* 좌측 텍스트 영역 — 좌측 60% 내 수직 중앙 */
  .text-area {
    position: absolute;
    top: 0;
    left: 0;
    width: 720px;
    height: 628px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    padding: 0 72px;
  }

  .tag-line {
    font-size: 28px;
    font-weight: 500;
    color: #00897B;
    letter-spacing: 0.5px;
    margin-bottom: 20px;
    text-transform: uppercase;
  }

  .headline {
    font-size: 52px;
    font-weight: 700;
    color: #FFFFFF;
    line-height: 1.25;
    letter-spacing: -1px;
    margin-bottom: 24px;
  }

  .headline .accent {
    color: #A5D6A7;
  }

  .sub {
    font-size: 30px;
    font-weight: 500;
    color: #B0BEC5;
    line-height: 1.5;
    margin-bottom: 44px;
    letter-spacing: -0.3px;
  }

  .cta-btn {
    display: inline-block;
    font-size: 28px;
    font-weight: 700;
    color: #FFFFFF;
    background: #00897B;
    padding: 18px 44px;
    border-radius: 4px;
    letter-spacing: 0px;
    white-space: nowrap;
  }

  /* 우측 상단 소형 배지 */
  .compare-badge {
    position: absolute;
    top: 48px;
    right: 500px;
    background: rgba(46, 125, 50, 0.85);
    border: 1.5px solid #4CAF50;
    border-radius: 4px;
    padding: 10px 20px;
    font-size: 24px;
    font-weight: 600;
    color: #FFFFFF;
  }

  /* 하단 데코 라인 */
  .deco-line {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(to right, #2E7D32, #00897B, #00BCD4);
  }
</style>
</head>
<body>
<div class="canvas">

  <!-- 우측 배경 -->
  <div class="bg-right"></div>

  <!-- 그라데이션 오버레이 -->
  <div class="gradient-overlay"></div>

  <!-- 텍스트 영역 -->
  <div class="text-area">
    <div class="tag-line">수수료 비교 분석</div>
    <div class="headline">GA 수수료 구조,<br><span class="accent">제대로 비교하세요</span></div>
    <div class="sub">같은 일인데 수수료가 다르다면?</div>
    <span class="cta-btn">GA 비교하기 →</span>
  </div>

  <!-- 비교 배지 -->
  <div class="compare-badge">객관적 데이터 비교</div>

  <!-- 하단 데코 -->
  <div class="deco-line"></div>

</div>
</body>
</html>FONT_DIRbg_image_paths    r>   build_html_1200x628rI      sR     Z  
 Z  
 Z  
 Z   #@ $1/ A2mw w    c                F    dt          dt          dt          dt          d|  dS )NrA   rB   rC   rD   u"  /Pretendard-Regular.otf') format('opentype');
    font-weight: 400;
  }

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

  body {
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
  }

  .canvas {
    width: 1080px;
    height: 1080px;
    position: relative;
    overflow: hidden;
  }

  /* 전체 배경 이미지 */
  .bg-full {
    position: absolute;
    top: 0;
    left: 0;
    width: 1080px;
    height: 1080px;
    background-image: url('file://ux  ');
    background-size: cover;
    background-position: center center;
  }

  /* 다크 그레이 반투명 오버레이 (opacity 0.55) */
  .dark-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 1080px;
    height: 1080px;
    background: rgba(21, 27, 30, 0.62);
  }

  /* 중앙 그라데이션 강화 (텍스트 가독성) */
  .center-gradient {
    position: absolute;
    top: 0;
    left: 0;
    width: 1080px;
    height: 1080px;
    background: radial-gradient(
      ellipse 900px 700px at center center,
      rgba(15, 20, 22, 0.55) 0%,
      rgba(15, 20, 22, 0.0) 70%
    );
  }

  /* 상단 배지 */
  .top-badge {
    position: absolute;
    top: 60px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(46, 125, 50, 0.9);
    border: 1.5px solid #66BB6A;
    border-radius: 4px;
    padding: 12px 36px;
    font-size: 26px;
    font-weight: 600;
    color: #FFFFFF;
    white-space: nowrap;
    letter-spacing: 0.5px;
  }

  /* 중앙 40% 영역 헤드라인 */
  .headline-zone {
    position: absolute;
    top: 216px;
    left: 0;
    right: 0;
    height: 432px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    padding: 0 80px;
  }

  .headline {
    font-size: 64px;
    font-weight: 700;
    color: #FFFFFF;
    line-height: 1.25;
    letter-spacing: -1.5px;
    margin-bottom: 32px;
    text-shadow: 0 2px 20px rgba(0,0,0,0.6);
  }

  .headline .accent {
    color: #A5D6A7;
  }

  /* 중앙 하단 25% — 서브 카피 */
  .sub-zone {
    position: absolute;
    top: 660px;
    left: 0;
    right: 0;
    height: 200px;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 0 80px;
  }

  .sub {
    font-size: 36px;
    font-weight: 500;
    color: #B2DFDB;
    text-align: center;
    line-height: 1.5;
    letter-spacing: -0.3px;
    text-shadow: 0 1px 12px rgba(0,0,0,0.5);
  }

  /* 하단 20% — CTA */
  .cta-zone {
    position: absolute;
    top: 864px;
    left: 0;
    right: 0;
    height: 216px;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .cta-btn {
    display: inline-block;
    font-size: 36px;
    font-weight: 700;
    color: #FFFFFF;
    background: #00897B;
    padding: 22px 72px;
    border-radius: 4px;
    letter-spacing: 0px;
    white-space: nowrap;
    text-shadow: none;
  }

  /* 하단 데코 라인 */
  .deco-line {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 5px;
    background: linear-gradient(to right, #2E7D32, #00897B, #00BCD4);
  }
</style>
</head>
<body>
<div class="canvas">

  <!-- 전체 배경 -->
  <div class="bg-full"></div>

  <!-- 다크 오버레이 -->
  <div class="dark-overlay"></div>

  <!-- 센터 그라데이션 보강 -->
  <div class="center-gradient"></div>

  <!-- 상단 배지 -->
  <div class="top-badge">수수료 비교 분석</div>

  <!-- 헤드라인 영역 -->
  <div class="headline-zone">
    <div class="headline">GA 수수료 구조,<br><span class="accent">제대로 비교하세요</span></div>
  </div>

  <!-- 서브 카피 -->
  <div class="sub-zone">
    <div class="sub">같은 일인데 수수료가 다르다면?</div>
  </div>

  <!-- CTA -->
  <div class="cta-zone">
    <span class="cta-btn">GA 비교하기 →</span>
  </div>

  <!-- 하단 데코 -->
  <div class="deco-line"></div>

</div>
</body>
</html>rE   rG   s    r>   build_html_1080x1080rL   ?  sQ     Z  
 Z  
 Z  
 Z  #> $1/ i2k^ ^rJ   c                b   |j                   d|j                   dz  }|j                  | d       t        d|        t	               5 }|j
                  j                         }	 |j                  ||d      }|j                  d|j                          d	
       |j                  d       |j                  t        |      d       t        d| d|j                         j                  dd       |j                          	 d d d        y # |j                          w xY w# 1 sw Y   y xY w)N_tmp_z.htmlzutf-8)encodingu     HTML 템플릿 저장: )widthheight)viewportzfile://networkidle)
wait_untili	  png)pathtypeu     캡처 완료: r   r   r   )parentstem
write_textr   r   chromiumlaunchnew_pagegotoresolvewait_for_timeout
screenshotstrstatst_sizeclose)html_contentoutput_pathrP   rQ   	html_filepbrowserpages           r>   capturerl   $  s   ""u[-=-=,>e%DDI8	%i[
12		 	a**##%	##u-O#PDII	 1 1 345-IP!!$'OO[!1O>%k]"[5E5E5G5O5OPQ4RRYZ[MMO	 	 MMO	 	s%   	D%%BD6D%D""D%%D.c                 n   t         j                  dd       t        d       t        d       t        d       t        j                         } t	               }t        dt        j                         | z
  dd       t        |j                               }t        d       t        j                         }t        |      }t        |t        d	d
       t        dt        j                         |z
  dd       t        d       t        j                         }t        |      }t        |t        dd       t        dt        j                         |z
  dd       t        d       t        d       t        dt                t        dt                t        dt        j                         | z
  dd       y )NT)parentsexist_okz<============================================================uB   GA 배너 M2-1 '정당한 대우' 하이브리드 이미지 생성u     배경 생성 소요: z.1fu   초
u)   [1/2] 1200x628 가로형 배너 생성...i  it  u
     소요: u-   [2/2] 1080x1080 정사각형 배너 생성...i8  u   완료!r   u     총 소요: u   초)
OUTPUT_DIRmkdirr   timer?   rb   r_   rI   rl   OUTPUT_1200x628rL   OUTPUT_1080x1080)t0bg_pathbg_strt1	html_widet2html_sqs          r>   mainr|   8  sX   TD1	(O	
NO	(O 
B!#G	$TYY[^C$8
>?"#F 

56	B#F+IIc2	Jtyy{2~c*%
01 

9:	B"6*GG%tT2	Jtyy{2~c*%
01	(O	)	B
 !	B 
!"	N499;r>#.c
23rJ   __main__)returnr   )rH   rb   r~   rb   )
rf   rb   rg   r   rP   intrQ   r   r~   None)r~   r   )#__doc__
__future__r   r(   sysrr   pathlibr   r$   playwright.sync_apir   __file__rX   TOOL_DIRrV   insertrb   r    rp   r*   rs   rt   homerF   r#   r"   r/   r0   r1   r?   rI   rL   rl   r|   __name__ rJ   r>   <module>r      s    #  
    /
 >   3x= ! AB
--55 77 499;88;  ED0-FuXx|_J(4D zF rJ   