
    iG                       d Z ddlmZ ddl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d      Zedz  dz  Zed	z  Zd
ZdZdZdZddZddZddZddZddZddZd Zedk(  r e        yy)u  M3-3 서울대보험쌤 × 영업지원 Google 광고 배너 생성
- m3-3-1200x628.png (가로형)
- m3-3-1080x1080.png (정사각형)

디자인 톤: 가장 밝은 톤 (크림 화이트 + 다크 골드)
배경: 카페 스타일 홈오피스, 아침 햇살
    )annotationsN)Path)sync_playwrightz0/home/jay/workspace/output/google-ads/banners/m3outputz	v4-hybridzbg_m3_3.jpgz0https://generativelanguage.googleapis.com/v1betazgemini-3-pro-image-previewzgemini-3.1-flash-image-previewum  Photographic scene of a bright, cafe-like home office workspace. Medium shot, front-facing eye-level angle. A clean white desk near a large window — morning light streaming through, creating soft natural lens flare on the left side. A person visible from the left side only: arm in a casual white shirt sleeve, hand on a white MacBook keyboard. Face completely outside the frame. On the desk: an open planner/notebook with neat handwriting (not readable), a ceramic mug with coffee (steam visible), and a small potted plant. Through the window: green trees or foliage visible — urban outdoor but natural feel. The wall behind is white with one small framed print (abstract, not text-based). The overall atmosphere is bright, calm, and full of quiet optimism — the first morning of a new beginning. Warm morning color temperature. No text. No logos. No icons. No graphics.c                     t         j                  j                  dt        t                     ddl} | j                         S )u7   gcloud_auth 모듈로 Bearer 토큰을 획득합니다.r   N)syspathinsertstrBASE_DIRgcloud_authget_access_token)r   s    \/home/jay/workspace/.worktrees/task-2116-dev1/tools/ai-image-gen/_backup/gen_m3_3_banners.pyget_auth_tokenr   4   s*    HHOOAs8}%''))    c                    t          d| d}d|  dd}t        j                  |||d      }|j                  dk(  r|S |r+t          d| d	| }d
di}t        j                  |||d      S |S )u6   SA 토큰 우선, 실패 시 API 키로 Gemini 호출.z/models/z:generateContentzBearer zapplication/json)AuthorizationContent-Type,  )headersjsontimeout   z:generateContent?key=r   )GEMINI_API_BASErequestspoststatus_code)	tokenapi_keymodelpayload
url_bearerheaders_bearerrespurl_keyheaders_keys	            r   _call_modelr'   ;   s    #$HUG3CDJ)0'8J\]N==^'SVWD3$%XeW4I'S%'9:}}WkQTUUKr   c                    t         j                         r9t         j                         j                  dkD  rt	        dt                 t         S t	        d       t               } t        j                  j                  dt        t                     ddl}|j                  d      }ddt        igigd	d
dgid}t        t        g}d}t!        |d      D ]  \  }}t	        d| d|        	 t#        | |||      }|j&                  dv r9t	        d|j&                   d|j(                  dd  d       d|j&                   }n|j&                  dk7  r8t	        d|j&                   d|j(                  dd         d|j&                   }|j+                         }
|
j-                  dg       }|s(t	        dt+        j.                  |
      dd         d}|d   j-                  di       j-                  dg       }t1        d |D        d      }|7t	        d|D cg c]  }t3        |j5                                c}        d}r|d    j-                  d!d"      }t7        j8                  |d    d#         }t         j;                  |       t	        d$t          d%t=        |      d&d'| d       t         c S  t?        d(|       # t$        $ r$}	t        |	      }t	        d|	        Y d}	~	d}	~	ww xY wc c}w ))uI   Gemini API로 배경 이미지를 생성하고 경로를 반환합니다.iP  u,   [배경] 기존 배경 이미지 재사용: u5   [배경] Gemini API로 배경 이미지 생성 중...r   NGEMINI_API_KEYpartstextresponseModalitiesIMAGETEXT)contentsgenerationConfig   u	     시도 u	   : 모델=u     요청 실패: )i  i  i  u     모델 접근 실패 (z: r   )zHTTP z  HTTP r   
candidatesu     응답에 candidates 없음: zNo candidatescontentc              3  *   K   | ]  }d |v s|  yw)
inlineDataN ).0ps     r   	<genexpr>z&generate_background.<locals>.<genexpr>y   s     A|q/@1As   	u     이미지 없음. parts: zNo inlineDatar6   mimeTypez
image/jpegdatau     [배경] 저장 완료:  (,z bytes, mime=u    배경 이미지 생성 실패: ) BG_PATHexistsstatst_sizeprintr   r   r	   r
   r   r   r   get_api_key	BG_PROMPTMODEL_IDFALLBACK_MODEL_ID	enumerater'   	Exceptionr   r+   r   getdumpsnextlistkeysbase64	b64decodewrite_byteslenRuntimeError)r   gar   r!   models_to_try
last_errorattemptr    r$   er<   r3   r*   
image_partr9   mime	img_bytess                    r   generate_backgroundr\   J   s   ~~GLLN22V;<WIFG	
ABEHHOOAs8}%nn-.G  34561GV3DEG
 01MJ#M15 &	')E734	ugug>D .,T-=-=,>b4C@QQRST !1!1 23Js"GD,,-R		$3/@AB !1!1 23Jyy{XXlB/
3DJJt4DTc4J3KLM(J1!!)R044WbAAeA4H
/0OAaffh0O/PQR(J,'++JE$$Z%=f%EF	I&*7)2c)nQ5G}UYTZZ[\]M&P 9*F
GGI  	QJ%aS)*	4 1Ps   +K K3	K0K++K0c                4    d| j                          }d| dS )u  1200x628 가로형 배너 HTML 생성.

    디자인 (업데이트: 딥 브라운 그라데이션 오버레이 → 프리미엄 다크 스타일):
    - Gemini 배경 전체
    - 딥 브라운 좌→우 그라데이션 오버레이 (m3-1 템플릿 A 적용)
    - 크림 헤드라인 #FFF8E7
    - 골드 서브카피 #C9A84C
    - CTA: 골드 그라데이션 배경, 다크 텍스트 #1A0E00
    - 골드 세로 액센트바
    file://u  <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-SemiBold.otf') format('opentype');
    font-weight: 600;
  }
  * { margin: 0; padding: 0; box-sizing: border-box; }

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

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

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

  /* 딥 브라운 그라데이션 오버레이 (강화: 좌측 완전 커버) */
  .gradient-overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to right,
      rgba(40,20,10,0.88) 0%,
      rgba(40,20,10,0.88) 38%,
      rgba(40,20,10,0.78) 52%,
      rgba(40,20,10,0.45) 68%,
      rgba(40,20,10,0.12) 82%,
      transparent 100%
    );
  }

  /* 골드 세로 액센트바 */
  .accent-bar {
    position: absolute;
    top: 80px;
    left: 0;
    width: 4px;
    height: 460px;
    background: linear-gradient(to bottom, #C9A84C, #D4B87A);
    border-radius: 2px;
  }

  /* 텍스트 영역: 좌측 62% */
  .text-area {
    position: absolute;
    left: 0;
    top: 0;
    width: 62%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 48px 56px 48px 60px;
    gap: 0;
  }

  /* 브랜드 뱃지 */
  .brand-badge {
    display: inline-flex;
    align-items: center;
    background: #C9A84C;
    color: #1A0E00;
    font-size: 40px;
    font-weight: 700;
    height: 48px;
    padding: 0 20px;
    border-radius: 6px;
    letter-spacing: -0.5px;
    margin-bottom: 28px;
    width: fit-content;
    white-space: nowrap;
  }

  /* 헤드라인: 크림 #FFF8E7 */
  .headline {
    font-size: 58px;
    font-weight: 700;
    color: #FFF8E7;
    line-height: 1.2;
    letter-spacing: -1px;
    margin-bottom: 20px;
    white-space: pre-line;
  }

  /* 지원 항목: 골드 #C9A84C */
  .support-items {
    font-size: 42px;
    font-weight: 500;
    color: #C9A84C;
    letter-spacing: -0.5px;
    margin-bottom: 36px;
    white-space: nowrap;
  }

  /* CTA 버튼: 골드 그라데이션 + 다크 텍스트 */
  .cta-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #C9A84C 0%, #D4B87A 100%);
    color: #1A0E00;
    font-size: 44px;
    font-weight: 700;
    height: 56px;
    width: 260px;
    border-radius: 6px;
    letter-spacing: -0.5px;
    box-shadow: 0 4px 16px rgba(201,168,76,0.35);
    white-space: nowrap;
  }
</style>
</head>
<body>
<div class="container">
  <!-- 배경 이미지 -->
  <div class="bg-image"></div>
  <!-- 딥 브라운 그라데이션 오버레이 -->
  <div class="gradient-overlay"></div>
  <!-- 골드 세로 액센트바 -->
  <div class="accent-bar"></div>
  <!-- 텍스트 영역 -->
  <div class="text-area">
    <div class="brand-badge">서울대보험쌤 · TOP사업단</div>
    <div class="headline">영업 못하는 게 아닙니다&#10;— <span style="color:#C9A84C">시스템</span>이 없었을 뿐</div>
    <div class="support-items">AI자동화&nbsp;&nbsp;|&nbsp;&nbsp;DB영업&nbsp;&nbsp;|&nbsp;&nbsp;정착금 1,000만원</div>
    <div class="cta-btn">무료 상담 신청 →</div>
  </div>
</div>
</body>
</html>resolvebg_pathbg_uris     r   make_html_1200x628rd      s8     w()*F)R #8 v$S_ _r   c                4    d| j                          }d| dS )um  1080x1080 정사각형 배너 HTML 생성.

    디자인:
    - Gemini 배경 전체
    - 크림 반투명 오버레이 opacity 0.38 (배경 아침 햇살/식물이 보이도록)
    - 중앙정렬 레이아웃
    - 딥 브라운 헤드라인 #3E2723
    - 다크 골드 서브카피 #A07828
    - CTA: 다크 골드 배경 #A07828, 크림 텍스트 #FFF8E7
    r^   u  <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-SemiBold.otf') format('opentype');
    font-weight: 600;
  }
  * { margin: 0; padding: 0; box-sizing: border-box; }

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

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

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

  /* 크림 반투명 오버레이 opacity 0.55 */
  .cream-overlay {
    position: absolute;
    inset: 0;
    background: rgba(255, 248, 231, 0.55);
  }

  /* 전체 컨텐츠 */
  .content {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 80px 72px;
    gap: 32px;
    text-align: center;
  }

  /* 크림 반투명 텍스트 패널 */
  .text-panel {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 860px;
    padding: 56px 48px;
    background: rgba(255, 248, 231, 0.80);
    border-radius: 12px;
    backdrop-filter: blur(4px);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 32px;
    text-align: center;
  }

  /* 브랜드 뱃지 */
  .brand-badge {
    display: inline-flex;
    align-items: center;
    background: #C9A84C;
    color: #1A0E00;
    font-size: 40px;
    font-weight: 700;
    height: 52px;
    padding: 0 22px;
    border-radius: 6px;
    letter-spacing: -0.5px;
    width: fit-content;
  }

  /* 헤드라인 */
  .headline {
    font-size: 62px;
    font-weight: 700;
    color: #3E2723;
    line-height: 1.2;
    letter-spacing: -1px;
    text-align: center;
    white-space: pre-line;
    text-shadow: 0 1px 8px rgba(255, 248, 231, 0.6);
  }

  /* 지원 항목 */
  .support-items {
    font-size: 44px;
    font-weight: 500;
    color: #A07828;
    letter-spacing: -0.5px;
    text-align: center;
    white-space: nowrap;
    text-shadow: 0 0 8px rgba(255, 248, 231, 1), 0 0 16px rgba(255, 248, 231, 0.8);
  }

  /* CTA 버튼: 골드 그라데이션 + 다크 텍스트 */
  .cta-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #C9A84C 0%, #D4B87A 100%);
    color: #1A0E00;
    font-size: 48px;
    font-weight: 700;
    height: 68px;
    width: 420px;
    border-radius: 6px;
    letter-spacing: -0.5px;
    box-shadow: 0 6px 24px rgba(201,168,76,0.40);
    white-space: nowrap;
    margin-top: 8px;
  }
</style>
</head>
<body>
<div class="container">
  <div class="bg-image"></div>
  <div class="cream-overlay"></div>

  <div class="text-panel">
    <div class="brand-badge">서울대보험쌤 · TOP사업단</div>
    <div class="headline">영업 못하는 게 아닙니다&#10;— <span style="color:#A07828">시스템</span>이 없었을 뿐</div>
    <div class="support-items">AI자동화&nbsp;&nbsp;|&nbsp;&nbsp;DB영업&nbsp;&nbsp;|&nbsp;&nbsp;정착금 1,000만원</div>
    <div class="cta-btn">무료 상담 신청 →</div>
  </div>
</div>
</body>
</html>r_   ra   s     r   make_html_1080x1080rf   9  s8     w()*F)R #8 q$SZ Zr   c           
        t         d| d| dz  }|j                  | d       t               5 }|j                  j	                         }	 |j                  ||d      }|j                  d|j                          d	
       |j                  d       |j                  j                  dd       |j                  t        |      ddd||d       t        d| d|j                         j                  dz  dd       |j!                          	 ddd       |j#                  d       y# |j!                          w xY w# 1 sw Y   1xY w)u:   HTML을 Playwright로 캡처하여 PNG로 저장합니다.
_tmp_m3_3_xz.htmlzutf-8)encoding)widthheight)viewportr^   networkidle)
wait_untili  Tparentsexist_okpngr   )ri   yrk   rl   )r	   typeclipu     [캡처] r=      .0f KB)N)
missing_ok)TMP_DIR
write_textr   chromiumlaunchnew_pagegotor`   wait_for_timeoutparentmkdir
screenshotr   rC   rA   rB   closeunlink)html_contentrk   rl   output_pathtmp_htmlr9   browserpages           r   capture_html_to_pngr     s@   :eWAfXU;;Hw7		 a**##%
	##u-O#PDII 0 0 234IO!!$'$$TD$AOO[!1Q&EO  K}B{/?/?/A/I/ID/PQT.UUYZ[MMO OOtO$ MMO s$   E
B7D-E-D??EEc                 "   t        d       t        d       t        d       t        j                  dd       t        j                  dd       	 t	               } t        dz  }t        d       	 | rt        |       }n$t        t        d	            j                  d
d      }t        |dd|       t        d|        t        dz  }t        d       	 | rt        |       }n$t        t        d	            j                  d
d      }t        |dd|       t        d|        t        d       t        d       t        d| d|j                         j                  dz  dd       t        d| d|j                         j                  dz  dd       t        d       y # t
        $ r&}t        d|        t        d       d } Y d }~nd }~ww xY w# t
        $ r}t        d|         d }~ww xY w# t
        $ r}t        d|         d }~ww xY w)Nz<============================================================u<   M3-3 서울대보험쌤 × 영업지원 배너 생성 시작Trp   u   [오류] 배경 생성 실패: uG   [폴백] 크림 화이트 그라데이션 배경으로 대체합니다.zm3-3-1200x628.pngu,   
[1] 1200x628 가로형 배너 생성 중...z/nonexistentz-background-image: url('file:///nonexistent');z>background: linear-gradient(135deg, #FFF8E7 0%, #F5E8C4 100%);i  it  u
     완료: u     [오류] zm3-3-1080x1080.pngu0   
[2] 1080x1080 정사각형 배너 생성 중...zKbackground: linear-gradient(160deg, #FFF8E7 0%, #F0DFA8 60%, #FFF8E7 100%);i8  z=
============================================================u   생성 완료!z  1200x628: r=   rw   rx   ry   z  1080x1080: )rC   r{   r   
OUTPUT_DIRr\   rI   rd   r   replacer   rf   rA   rB   )rb   rX   out_1200	html_1200out_1080	html_1080s         r   mainr     s    	(O	
HI	(OMM$M.TD1%' //H	
9:*73I +4+?@HH?PI 	ItS(;
8*%& 00H	
=>+G4I+D,@AII?]I 	ItT8<
8*%&
 
/	
	L
"X]]_%<%<t%CC$H
MN	M(2hmmo&=&=&DS%I
NO	(OY  /s34WX&  A3 "  A3 sJ   
F 0AG AG1 	G(G		G	G.G))G.1	H:H		H__main__)returnr   )
r   r   r   z
str | Noner    r   r!   dictr   zrequests.Response)r   r   )rb   r   r   r   )
r   r   rk   intrl   r   r   r   r   None)__doc__
__future__r   rO   r   r   timepathlibr   r   playwright.sync_apir   __file__r   r   r   r{   r?   r   rF   rG   rE   r   r'   r\   rd   rf   r   r   __name__r7   r   r   <module>r      s    #   
    / >  DE

X

+
M
! E'4 0 
&*<HBk\fV%07t zF r   