
    KiI                        d 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 e
dz  Zedz  Zedz  Zed	z  Zej!                  d
d
       ej"                  j%                  d ee
dz               ddlZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!defdZ"dedefdZ#dedefdZ$ded eddfd!Z%e&d"k(  r ej                         Z' e(d#        e(d$        e(d%e         e(d#        e"       Z) e$e)      Z* e%e*e        ej                         e'z
  Z+ e(d&ejX                   d'e+d(d)       ej[                         r4 e(d*ej]                         j^                  d+z  d,d-        e(d.e        yyy)/u   
Production A-5 (CTA) — Meta Carousel Slide (밝은 톤 재제작)
밝고 따뜻한 크림/골드 톤 — A-4와 연속되는 캐러셀 클라이맥스
Hybrid: Gemini background + Playwright HTML overlay
Output: /home/jay/workspace/output/meta-ads/a-group-v6/production/meta-A5-cta.png
    N)Path)sync_playwright)WORKSPACE_ROOTFONT_DIRz%output/meta-ads/a-group-v6/productionz_bg_a5_cta.jpgz_a5_cta_template.htmlzmeta-A5-cta.pngTparentsexist_okztools/ai-image-gen      $   .   D   gQ?gzG?z0https://generativelanguage.googleapis.com/v1betazgemini-3-pro-image-previewzgemini-3.1-flash-image-previewzgemini-2.5-flash-preview-04-17z3https://www.googleapis.com/auth/generative-languageu~	  
Warm bright morning sunlight streaming through large modern windows into a premium consultancy office.
Soft golden light particles floating in the air. Warm cream and gold color palette dominant.
Bright, hopeful, professional atmosphere. Shallow depth of field, bokeh effect.
No people, no text, no furniture in focus. High-end commercial photography style. Square format 1:1.

COMPOSITION: 1:1 square, 1080x1080px. Full bleed. No text, no people, no faces.

VISUAL CONCEPT:
Luxurious bright morning scene — a premium consulting or financial advisory office space
bathed in warm golden morning sunlight. Light streams dramatically through floor-to-ceiling
windows, creating beautiful lens flares and golden bokeh particles. The space feels aspirational,
warm, and achievable — the "destination" at the end of a journey.

BACKGROUND ELEMENTS:
- Warm cream / ivory base (#F5F0E8 family) — bright and luminous
- Brilliant warm golden sunlight (#E8C870 / #C9A84C tones) streaming from upper-right or upper-center
- Soft bokeh circles — warm gold and cream tones, out-of-focus background elements
- Very subtle architectural lines (window frames, clean edges) just barely visible
- Golden light particles / dust motes floating in the air, catching light
- Top-center: brightest area — convergence of light rays
- Overall: luminous, airy, premium, "threshold of success" feeling

MOOD / ATMOSPHERE:
- Achievement. Clarity. Warmth. Forward momentum.
- The brightest, most hopeful moment in a journey
- Premium Korean financial advisory aesthetics
- "Just one more step" — action-ready, confident energy
- Continuation of a warm cream background series (matching slide 4)

COLOR PALETTE:
- Primary: Warm cream (#F5F0E8), golden ivory (#F0E8D0), bright off-white
- Golden accent glow: #C9A84C to #E8C870 — warm, rich, visible but not harsh
- No dark tones whatsoever — this is the bright payoff slide
- No cool tones — only warm cream/gold/ivory family
- Maximum warmth and luminosity

STYLE REQUIREMENTS:
- NO people, faces, hands, or figures
- NO text, numbers, labels, or UI elements
- NO dark zones — keep entire image bright and luminous
- Photorealistic commercial photography quality
- Premium advertising background — supportive of overlaid text
- The content overlay will use dark text (#1A202C), so background must remain bright
- Ensure center-bottom area has some texture/depth for CTA button visibility
returnc            
         t         j                         rt        dt                 t         S t        d       t        j                  t
              dt        dt        j                  ffd} t        j                         }t        t        t        fD ]  }t        d|        	  | |      }|j                  dv rt        d	|j                   d
       C	 |j                          |j'                         }|j)                  dg       }|st        dt        |      d d         |d   j)                  di       j)                  dg       }t+        d |D        d       }|7|D 	cg c]  }	d|	v s|	j)                  dd       }
}	t        d|
d d         |d   j)                  dd      }|d   d   }d|v rdnd}t         j-                  |      }|j/                  t1        j2                  |             t        d |j4                   d!|j7                         j8                  d"d#t        j                         |z
  d$d%       |c S  t;        d&      # t        $ r}t        d|        Y d }~d }~ww xY w# t        j                   $ rG}t        d|j"                  j                   d|j"                  j$                  d d         Y d }~:d }~ww xY wc c}	w )'Nu(   [BG] 기존 배경 이미지 재사용: u1   [BG] Gemini API로 배경 이미지 생성 중...model_idr   c                     t          d|  d}d dd}ddt        igigdd	d
gid}t        j                  |||d      S )Nz/models/z:generateContentzBearer zapplication/json)AuthorizationzContent-TypepartstextresponseModalitiesIMAGETEXT)contentsgenerationConfig,  )headersjsontimeout)GEMINI_API_BASE	BG_PROMPTrequestspost)r   urlr   payloadtokens       B/home/jay/workspace/tools/ai-image-gen/gen_production_a5_cta_v2.py_callz"generate_background.<locals>._callc   sk     !(3CD&ug..

 "VY$7#89:!57H I
 }}S'MM    u     -> 모델 시도: u     [WARN] 요청 실패: )i  i  i  z  [WARN] HTTP u    — 다음 모델 시도z  [ERROR] HTTP z: r   
candidatesu     [WARN] candidates 없음:    r   contentr   c              3   *   K   | ]  }d |v s|  yw)
inlineDataN ).0ps     r&   	<genexpr>z&generate_background.<locals>.<genexpr>   s     ?q\Q->?s   	r    u&     [WARN] 이미지 없음. 텍스트:    r-   mimeTypez
image/jpegdatajpegz.jpgz.pngu   [BG] 완료:  (,z bytes, .1fu   초)u    [BG] 모든 모델 시도 실패)BG_PATHexistsprintgcloud_authget_service_account_tokenSCOPEstrr!   ResponsetimeMODEL_PRIMARYMODEL_FALLBACKMODEL_FALLBACK2	Exceptionstatus_coderaise_for_status	HTTPErrorresponser   r   getnextwith_suffixwrite_bytesbase64	b64decodenamestatst_sizeRuntimeError)r'   t0r   resper5   r)   r   img_partr0   textsmimeb64extfpathr%   s                  @r&   generate_backgroundr^   [   s   ~~8	BC	
=>11%8E
N 
N 1 1 
N 
B"NOD %$XJ/0	?D
 .N4#3#3"44MNO	!!#
 yy{XXlB/
0T4C0ABC1!!)R044WbA?E?F05E11QUU62&EEE:5!9+FG&**:|D&v. D.f##C(&**3/0ejj\EJJL,@,@+C8DIIKXZN[^K__cdeK%N 9
::G  	,QC01	 !! 	OAJJ$:$:#;2ajjoods>S=TUV	 Fs<   &II8$	K.K	I5I00I58K<KKbg_pathc                 B   d| j                          }t        t              }dj                  g d| d| d| d| d| d| d	| d
t         dt         dt
         dt         dt         dt         dt         dt         d      S )Nfile://r2   z<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<style>
  @font-face {
    font-family: 'Pretendard';
    src: url('file://z/PretendardVariable.ttf') format('truetype');
    font-weight: 100 900;
  }
  @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; }

  html, body {
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #F5F0E8;
  }

  /* ── Canvas: background image ── */
  .canvas {
    width: 1080px;
    height: 1080px;
    position: relative;
    background-image: url('u  ');
    background-size: cover;
    background-position: center center;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    overflow: hidden;
  }

  /* ── Very light warm overlay — preserves bright background ── */
  .overlay {
    position: absolute;
    inset: 0;
    background:
      radial-gradient(ellipse 80% 60% at 50% 42%, rgba(255, 252, 240, 0.35) 0%, transparent 70%),
      linear-gradient(
        180deg,
        rgba(255, 252, 245, 0.45) 0%,
        rgba(255, 250, 238, 0.25) 25%,
        rgba(245, 240, 228, 0.10) 55%,
        rgba(240, 234, 215, 0.35) 80%,
        rgba(235, 228, 210, 0.55) 100%
      );
    pointer-events: none;
  }

  /* All content above overlay */
  .content {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0 64px;
  }

  /* ── PAGE INDICATOR (top-right absolute) ── */
  .page-indicator {
    position: absolute;
    top: 52px;
    right: 58px;
    font-family: 'Pretendard', sans-serif;
    font-size: u  px;
    font-weight: 500;
    color: rgba(120, 100, 60, 0.55);
    letter-spacing: 0.06em;
    z-index: 10;
  }

  /* ── BRAND LOGO — top center (10%) ── */
  .brand-logo {
    margin-top: 54px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
  }

  .brand-emblem svg {
    width: 56px;
    height: 56px;
    filter: drop-shadow(0 2px 10px rgba(201, 168, 76, 0.55));
  }

  .brand-name {
    font-family: 'Pretendard', sans-serif;
    font-size: u  px;
    font-weight: 700;
    color: #C9A84C;
    letter-spacing: 0.05em;
    text-shadow: 0 1px 4px rgba(255,255,255,0.7);
  }

  /* ── HEADLINE SECTION — center ── */
  .headline-section {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0 20px;
    margin-top: -10px;
  }

  .headline {
    font-family: 'Pretendard', sans-serif;
    font-size: z+px;
    font-weight: 900;
    line-height: u  ;
    letter-spacing: -0.030em;
    color: #1A202C;
    word-break: keep-all;
    margin-bottom: 32px;
  }

  .headline .accent {
    color: #C9A84C;
    font-weight: 900;
    text-decoration: underline;
    text-decoration-color: rgba(201, 168, 76, 0.65);
    text-decoration-thickness: 3px;
    text-underline-offset: 7px;
  }

  /* ── Gold divider: line-dot-line ── */
  .divider {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    max-width: 520px;
    margin-bottom: 30px;
  }

  .divider-line {
    flex: 1;
    height: 1.5px;
    background: linear-gradient(90deg, transparent, rgba(201, 168, 76, 0.55), transparent);
  }

  .divider-dot {
    width: 7px;
    height: 7px;
    background: #C9A84C;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 6px rgba(201, 168, 76, 0.70);
  }

  /* ── SUBCOPY ── */
  .subcopy {
    font-family: 'Pretendard', sans-serif;
    font-size: z+px;
    font-weight: 400;
    line-height: un  ;
    color: rgba(40, 40, 50, 0.80);
    text-align: center;
    word-break: keep-all;
    letter-spacing: -0.01em;
  }

  /* ── BOTTOM SECTION ── */
  .bottom-section {
    width: 100%;
    padding: 0 0 56px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 22px;
    flex-shrink: 0;
  }

  /* ── CTA BUTTON ── */
  .cta-btn {
    width: 100%;
    max-width: 860px;
    background: linear-gradient(
      135deg,
      #C9A84C 0%,
      #E8C870 40%,
      #D4AD52 70%,
      #B8922A 100%
    );
    color: #ffffff;
    font-family: 'Pretendard', sans-serif;
    font-size: u  px;
    font-weight: 900;
    letter-spacing: -0.02em;
    text-align: center;
    padding: 34px 48px;
    border-radius: 18px;
    word-break: keep-all;
    box-shadow:
      0 0 48px rgba(201, 168, 76, 0.50),
      0 8px 32px rgba(0, 0, 0, 0.20),
      inset 0 2px 0 rgba(255, 255, 255, 0.38),
      inset 0 -3px 0 rgba(0, 0, 0, 0.12);
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    position: relative;
    overflow: hidden;
  }

  .cta-btn::after {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 48%;
    background: linear-gradient(180deg, rgba(255,255,255,0.18) 0%, transparent 100%);
    border-radius: 18px 18px 0 0;
  }

  /* ── TRUST ANCHOR ── */
  .trust-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 20px;
  }

  .trust-item {
    display: flex;
    align-items: center;
    gap: 7px;
    font-family: 'Pretendard', sans-serif;
    font-size: u  px;
    font-weight: 500;
    color: rgba(80, 80, 90, 0.60);
    letter-spacing: 0.01em;
  }

  .trust-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
  }

  .trust-sep {
    width: 4px;
    height: 4px;
    background: rgba(201, 168, 76, 0.45);
    border-radius: 50%;
    flex-shrink: 0;
  }

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

  <!-- Warm overlay -->
  <div class="overlay"></div>

  <!-- Page indicator (absolute) -->
  <div class="page-indicator">5 / 5</div>

  <!-- Content layer -->
  <div class="content">

    <!-- BRAND LOGO: top center -->
    <div class="brand-logo">
      <div class="brand-emblem">
        <svg viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg">
          <defs>
            <linearGradient id="goldGrad" x1="0%" y1="0%" x2="100%" y2="100%">
              <stop offset="0%" style="stop-color:#E8C870"/>
              <stop offset="50%" style="stop-color:#C9A84C"/>
              <stop offset="100%" style="stop-color:#B8922A"/>
            </linearGradient>
          </defs>
          <!-- Shield outline -->
          <path d="M27 4 L47 13.5 L47 31 C47 41.5 37 48.5 27 51.5 C17 48.5 7 41.5 7 31 L7 13.5 Z"
                fill="rgba(201,168,76,0.12)" stroke="url(#goldGrad)" stroke-width="1.8"/>
          <!-- Star -->
          <path d="M27 14.5 L29.6 22.2 L37.8 22.2 L31.2 27.0 L33.8 34.7 L27 29.9 L20.2 34.7 L22.8 27.0 L16.2 22.2 L24.4 22.2 Z"
                fill="url(#goldGrad)"/>
        </svg>
      </div>
      <div class="brand-name">서울대보험쌤</div>
    </div>

    <!-- HEADLINE SECTION: center -->
    <div class="headline-section">
      <h1 class="headline">
        전략을 바꿀 준비가 됐다면,<br>지금 <span class="accent">딱 한 번</span> 물어보세요.
      </h1>

      <!-- Divider: line-dot-line -->
      <div class="divider">
        <div class="divider-line"></div>
        <div class="divider-dot"></div>
        <div class="divider-line"></div>
      </div>

      <!-- Subcopy -->
      <p class="subcopy">
        서울대보험쌤 팀장이 직접 답합니다.<br>조건 없는 상담, 당신 상황에 맞는 방향 제시.
      </p>
    </div>

    <!-- BOTTOM: CTA + Trust -->
    <div class="bottom-section">

      <!-- CTA Button -->
      <div class="cta-btn">무료 상담 신청하기</div>

      <!-- Trust anchor -->
      <div class="trust-row">
        <div class="trust-item">
          <!-- Star icon -->
          <svg class="trust-icon" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M10 2.5L11.9 7.8L17.5 7.8L13.1 11.3L14.9 16.6L10 13.1L5.1 16.6L6.9 11.3L2.5 7.8L8.1 7.8Z"
                  fill="#C9A84C"/>
          </svg>
          조건 없음
        </div>
        <div class="trust-sep"></div>
        <div class="trust-item">
          <!-- Check circle icon -->
          <svg class="trust-icon" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
            <circle cx="10" cy="10" r="8" stroke="#C9A84C" stroke-width="1.6"/>
            <circle cx="10" cy="10" r="3" fill="#C9A84C"/>
          </svg>
          무료 상담
        </div>
        <div class="trust-sep"></div>
        <div class="trust-item">
          <!-- Person icon -->
          <svg class="trust-icon" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
            <circle cx="10" cy="7" r="3.5" stroke="#C9A84C" stroke-width="1.6"/>
            <path d="M3.5 18C3.5 14.9 6.4 12.5 10 12.5C13.6 12.5 16.5 14.9 16.5 18"
                  stroke="#C9A84C" stroke-width="1.6" stroke-linecap="round"/>
          </svg>
          팀장 직접 응대
        </div>
      </div>

    </div>

  </div><!-- /content -->
</div><!-- /canvas -->
</body>
</html>)resolver@   r   join
_SIZE_22PX
_SIZE_68PX_LH_1_22
_SIZE_36PX_LH_1_68
_SIZE_46PX
_SIZE_26PX)r_   bg_urlfont_dirs      r&   
build_htmlrm      s   w()*F8}Hs s  s Zs s Zs s" Z#s" #s, Z-s, -s6 Z7s6 7s@ ZAs@ Asd #8esd($est |ustusf |gsfgsP |QsPQsT UsT,Usl |mslmsp qspqsn |osn'os| |}s|u}s sr(   c                 v    t        |       }t        j                  |d       t        dt                t        S )Nzutf-8)encodingu   [HTML] 오버레이 저장: )rm   	HTML_PATH
write_textr<   )r_   html_contents     r&   
write_htmlrs     s5    g&L8	(
45r(   	html_pathout_pathc           
      v   t        d       t               5 }|j                  j                  ddg      }	 |j	                  ddd      }|j                  d| j                          d	
       |j                  d       |j                  d       |j                  j                  dd       |j                  t        |      dddddd       |j                          	 d d d        |j                         j                  dz  }t        d| d|dd       y # |j                          w xY w# 1 sw Y   OxY w)Nu$   [RENDER] Playwright 캡처 시작...z--no-sandboxz--disable-dev-shm-usage)argsi8  )widthheight)viewportra   networkidle)
wait_untilz+async () => { await document.fonts.ready; }i  Tr   pngr   )xyrx   ry   )pathtypeclip   u   [RENDER] 완료: r7   .0fz KB))r<   r   chromiumlaunchnew_pagegotorb   evaluatewait_for_timeoutparentmkdir
screenshotr@   closerR   rS   )rt   ru   r0   browserpagesize_kbs         r&   capturer     s&   	
01		 a**##.:S)T#U	##tt-L#MDII	 1 1 345-IPMMGH!!$'OO!!$!>OO]1ttD   MMO  mmo%%,G	hZr'#d
;< MMO s#   D/BDD/D,,D//D8__main__z<============================================================u-   Production A-5 (CTA) — 밝은 톤 재제작u   출력: u
   
[완료] z  (r9   u   초 총 소요)u          파일 크기: r   r   z KBu          경로: )0__doc__rO   sysrB   pathlibr   r!   playwright.sync_apir   
gen_configr   r   
OUTPUT_DIRr:   rp   OUT_PATHr   r   insertr@   r=   rd   rj   rg   ri   re   rf   rh   r   rC   rD   rE   r?   r    r^   rm   rs   r   __name__t_startr<   bghtmlelapsedrQ   r;   rR   rS   r.   r(   r&   <module>r      s    
    / / EE
**11	++ 
    - 3~(<<= > 




D.22G-	b<;T <;Bw w wt  =t =t = =0 zdiikG	(O	
9:	HXJ
 	(O		Bb>DD(diikG#G	Kc'#o
FG&x}}'>'>'Ec&J#NOz*+  r(   