
    zTjV{                     D   d Z ddlZddlZddlZddlmZ  ee      j                  Z	ej                  j                  d ee	             ddlZddlZddlZddlZej*                  j                  dz  Zedz  Zedz  Ze	dz  ZdZd	j5                  g d
      Zd	j5                  g d      ZdZd Zd ZddZ d Z!d Z"d Z#d Z$d Z%d Z&d Z'e(dk(  rR ejR                         Z*e*jW                  ddg d       e*jY                         Z- e"e#e%e&e'de-j\                             yy)u@  s38 — 옥탑 23샷 전체: 경량 레이아웃 콘티 + prev 단독 참조 스틸 (2026-07-13).

x_quad v1~v3 + 체이닝 실험 판정 지식 종합(사용자 확정 규칙):
- 콘티 = 초경량 레이아웃 선화(LIGHT_STYLE — 질감 오염 방지)로 전 샷 시트.
- 스틸 참조 규칙:
  * prev(시각 관련 이전샷, s35 판정) 있으면 → 참조 = 이전샷 실사 '오롯이
    하나만' (콘티·플레이트·캐릭터·소품 전부 제외 — 자세·장소·의상·소품을
    prev 사진이 잠금, x_still_chain 실증)
  * prev 없으면 → 경량 콘티 패널 + 배경 플레이트 + 캐릭터/소품 참조.
- 자세 정본·carried state·pose_fix 교정본(텍스트)은 전 샷 안전망 유지.

사용: backend/.venv/bin/python s38_lightconti_full.py --only
     <conti|crop|stills|html>
    N)Paths38panelsstillszs38_lightconti_full.htmls38_light_v1
)
u=   STYLE — LAYOUT-ONLY THUMBNAIL SKETCH: the lightest possiblez>director's layout drawing. THIN, CLEAN, UNIFORM PENCIL CONTOURzBLINES ONLY on pure white paper. Absolutely NO shading, NO tone, NOz@hatching, NO texture, NO grayscale fill, NO light-and-shadow, NOzBfacial features beyond a bare head outline, NO clothing detail, NOzAmaterial rendering. Each panel contains ONLY: the camera framing,z?each figure as a simple correct-proportion human contour in itszAexact pose and screen position/size, and the few major set massesz>as plain outline shapes. It must read as a quick layout guide,znever as a finished drawing.)
zBEXPRESSIONS ARE ACTED, NEVER ANATOMICAL: when the text describes azDperson's eyes, face or presence emotionally or figuratively (vacant,zDhollow, dazed, burning, lifeless gaze and the like), it describes anuA   ACTOR'S PERFORMANCE captured by a real camera — realize it ONLYzAthrough gaze direction, focus, eyelids, facial muscles, stillnesszBand posture. Every living person's eyes remain anatomically normalzChuman eyes with a natural iris and pupil, natural sclera and normalzBproportions; NEVER whiten, blank out, cloud over, glow, enlarge oru>   otherwise alter eyeballs, skin or anatomy — unless the storyzAexplicitly declares that being non-human or supernatural in form.uQ  LAYOUT SKETCH — a bare thin-line layout guide, a REFERENCE ONLY: take from it ONLY the camera framing, figure placement, pose and size/depth order. It carries ZERO visual style — every texture, material, light and all realism come from the text and the photographic reference. Never let any line-drawing quality leak into the output.c                  H    t        j                  t        j                        S N)F	load_planWPLAN     W/Users/manta/Documents/Projects/TheRoad-I1/scratchpad/forest_exp/s38_lightconti_full.py_plan37r   F   s    ;;qvvr   c           	         t        j                         }|d   D ci c]  }|d   |
 }}g }t         j                  D ]K  }||   d   }t        t	        j
                  |            D ]   \  }}|j                  |||||   d   f       " M | d   }	|	d d |	dd  g}
t        d |
D              D ]<  \  }}|j                  t         j                  |||t         j                     d   f       > |S c c}w )Ngroupskeyshotsplace_enint_tags   c              3   &   K   | ]	  }|s|  y wr
   r   ).0cs     r   	<genexpr>z_sheet_jobs.<locals>.<genexpr>T   s     5A1as   )r   _s35
EXT_GROUPS	enumerateR_chunksappend	INT_GROUP)p37plan35ggmapjobsgkr   ichunkr   chunkss              r   _sheet_jobsr.   J   s    VVXF!'!12!1AAeHaK!1D2DllR!!!))E"23HAuKKQtBx
';<= 4  :HrlHQRL)F5555Q[[!U!++&z24 	5 6 K 3s   C-c                 h   g }t        |d      D ]  \  }}t        j                  t        j                  |         }|j	                  |i       }| j	                  di       j	                  |      xs i }	|	j	                  d      xs |j	                  dd      }
|	j	                  d      xs |j	                  dd      }|	j	                  d      xs2 | j	                  d	i       j	                  |i       j	                  dd      }d
| d| d}|r|dt        j                  |       dz  }|dt        j                  |d          z  }|
r|dt        j                  |
       z  }|r|dt        j                  |       z  }|r|dt        j                  |      z   z  }|j                  |        |S )N   pose_fixmovement_enmovement 
figures_enfigures
carried_enint_contzPANEL  ()u    — TIME OF DAY (lock): .z&
  SHOT TEXT (authoritative, Korean): descz
  MOVEMENT (follow exactly): u7   
  FIGURES — apparent size & depth (follow exactly): z2
  CARRIED STATE (persist exactly across panels): )	r    r!   SHOT_keygetS_time_of_softenr#   )r%   mvr,   include_timelinesr+   tagsmfixr3   r6   carriedlines                 r   _panel_linesrL   Z   s   EE1%3FF166#;FF3Oggj"%))#.4"77=)BQUU:r-B'','?155B+?'',' DCGGJ,C-0Sb\-0Sr-B 	 s"SE#/

3/@BBD YYqy)*, 	-5aii6I5JKKD ##$99W#5"68 9DJyy)* +DT- &. Lr   c                     g }| j                  dg       D ]A  t        fd|D              s|j                  dt        j                  d         z          C |S )N
pose_canonc              3   ,   K   | ]  }|d    v   yw)r   Nr   )r   tits     r   r   z _pose_clauses.<locals>.<genexpr>y   s     /AqBwKs   u   IMMOBILE CHARACTER POSE — CANONICAL (identical wherever this character appears in ANY panel; on any conflict THIS POSE WINS): pose_en)r?   anyr#   r@   rB   )r%   r,   outrQ   s      @r   _pose_clausesrU   v   sZ    
CgglB'///JJ%'(yyI'?@A ( Jr   c                     t               } t        j                         }t        j                  |      }t        dz  t
         dz  j                         rt        j                  t
              ni }|j                  di       }t        j                  dd       t        |       D ]  \  }}}}t        j                  t        |            \  }	}
}}d|
 dt        d| g}t!        | |      }|r |j#                  d	j%                  |             |d
d	j%                  t'        | ||            gz  }|	t        |      kD  rC|j#                  t        j(                  j*                  j-                  t        |      |	             |j#                  ddj%                  d t/        dt        |      dz         D              z   dz          dj%                  |      }d| d| d}||||	|d|| d| <   t        j0                  d| d| |d |t        |z         t3        d| d| dt        |       d|         t        j4                  t
        |       y )Nplansz.jsonsheetsTparentsexist_okz"Draw ONE storyboard layout sheet: r;   z)THE LOCATION (same in all drawn panels): r   z.PANELS (one shot per panel, Korean shot text):)n_shotsslotszTABSOLUTELY NO TEXT anywhere: the ONLY allowed marking is a small shot number digit (, c              3   2   K   | ]  }t        |        y wr
   )str)r   ns     r   r   zstage_conti.<locals>.<genexpr>   s     A(@1A(@s   r0   z) in a corner INSIDE each drawn panel. The grid fills the entire image edge-to-edge; panels separated only by thin straight black gutter lines at the exact stated positions; ALL PANELS EXACTLY THE SAME SIZE.

conti38__.png)gkeyfiler   r]   prompt
s38_conti_)refssizeout_pathz[conti] : u   샷 → )r   r   r   	_movementHEREr   existsr   r   
setdefaultOUTmkdirr.   _grid_nlenLIGHT_STYLErU   r#   joinrL   CBLANKformatrangeimg_gptprint	save_plan)r%   r&   rC   planrX   r*   r+   r,   r   r]   layoutrk   _arpartspcrh   fns                    r   stage_contir      s+   
)CVVXF	
V	B!%TF%.!@ H H J1;;t 	__Xr*FIIdTI*"-c"2Auh#$99SZ#8 vtS0:7zB

 3&LL2'<IIl3E23
 	
 3u:LL))#e*E)JK)iiAaUa(@AAB11	2 U#t1QCt$')2(-A"Qqc{			Jrd!A3'd8	%AaS3u:,hrd;<= #3> KKdr   c                     ddl m}  dd l}t        j                  t
              }t        j                  dd       ddddd	}|d
   j                         D ]  \  }}| j                  t        |d   z        j                  d      }|j                  d      j                  d       }|j                         }|rsd}	t        d|d   |	z
        t        d|d   |	z
        t        |j                   d   |d   |	z         t        |j                   d   |d   |	z         f}|j#                  |      }|j                   \  }
}||d      \  }}|j%                  |j                  d            }|dk  }d }|dkD  r ||j'                  d      |dz
  |
      ng }|dkD  r ||j'                  d      |dz
  |      ng }dg|z   |
gz   }dg|z   |gz   }t)        |d         D ]]  \  }}||z  ||z  }}||   dz   ||   dz   ||dz      dz
  ||dz      dz
  f}|j#                  |      j+                  t        | dz         _ t-        d| dt/        |d          d| d|         y )Nr   )ImageTrY   )   r0   )r   r   )   r   )   r   )r   r      r   rX   rg   RGBLc                     | dk  rdS dS )N      r   r   )vs    r   <lambda>zstage_crop.<locals>.<lambda>   s    S#2Ga2Gr   r   r0   r   r   r]   x   c                    t        |       D cg c]  \  }}|dkD  s| }}}g }|D ]9  }|r#||d   d   z
  dk  r|d   j                  |       (|j                  |g       ; |D cg c]B  }|dz  t        |      t        |      z  cxk  r|dz  k  rn nt        |      t        |      z  D }}t        |      |k(  r|S t	        |      D 	cg c]  }	||	dz   z  |dz   z   c}	S c c}}w c c}w c c}	w )Ng?r   g{Gz?gQ?r0   )r    r#   sumru   r{   )
profilen_expecttotalr+   r   candgsxcentersks
             r   _lineszstage_crop.<locals>._lines   s   "+G"4A"4$!QDA"4DAB!bfRj.A-rFMM!$IIqcN	 
 24 IA$,Q#a&G54<G 1vQ'G I7|x'"8_., QUO15,. . BI.s   C&C&(AC,C1)axisr   re   z[crop] rm   u	   패널 v=z h=)PILr   numpyr   r   r   OUTPrs   itemsopenrr   convertpointgetbboxmaxminrk   cropasarraymeanr    saver}   ru   )r   npr   GRIDMAPskeyshsheetmaskbboxpadWIDTHHEIGHTcolsrowsarrdarkr   v_linesh_linesxsysr+   rF   r   rboxs                             r   
stage_cropr      s   ;;tDJJtdJ+V6:GN((*b

3F+,44U;}}S!''(GH||~C47S=)3q$q'C-+@

1tAw}5

1tAw}57D JJt$E

vR[)
djjs+,Sy	.  ax *D1He< 	 ax *D1Hf= 	S7]eW$S7]fX%7,FAst8Q$YqAa519beaiAEQ1q5	AFCJJsO  3%t!45 - 	vRBwK 017)G9 	Q +r   c                 ,   t        j                         }|d   D ci c]  }|d   |
 }}t         j                  D cg c]  }||   d   D ]  }|  c}}t        | d         z   }t	        t        |      t        j                        S c c}w c c}}w )Nr   r   r   r   )r   )r   r   r   listsortedsetr!   r>   )r%   r&   r'   r(   r*   rP   tagss          r   _all_tags_story_orderr      s    VVXF!'!12!1AAeHaK!1D2@"d2hw.?A.?A@
s:
 D#d)(( 3@s
   BBc                     t               } t        |       }dj                  g d      }ddddddddiddd	giddiddid
g d
ddidgd}t        |D ch c]  }t	        j
                  |      d    c}      }dj                  d |D              }t        j                         }|d   D ci c]  }|d   |
 c}t        j                  D 	ci c]  }	|	   d   D ]  }||	  c}}	j                  | d   D ci c]  }|t        j                   c}       i | d   D ]  }
|
d   D ]
  }|
d   |<     dj                  fd|D              }t        j                  d|d| d| |      }|d   D ci c]  }|d   |
 }}|D cg c]	  }||vs| }}|rt        d|       |D ]M  }||   d   }|s||vs,t	        j
                  |      t	        j
                  |      k\  s>t        d| d|        t        j                  t              }|j!                  d      r|j!                  d       s|d   |d <   ||d<   t        j"                  t        |       |D ]>  }||   }t%        d!| d|d    d"|d#   d$d%         |d&   s+t%        d'|d&   d$d(         @ y$c c}w c c}w c c}}	w c c}w c c}w c c}w ))u  prev 판정 v3 — ★유일 기준=배경(장소) 동일성 (2026-07-13 사용자 정정).

    v2 결함: 스토리·인물 연속만으로 prev 를 지정해, 이동 후 다른 장소인
    샷(S13sh4 골목)이 앞 장소(S11sh4 계단)의 배경을 물려받아 장소 이탈.
    v3: 배경이 사실상 같은 지점일 때만 prev, 아니면 null(→플레이트 참조).
    r   )uQ   당신은 촬영 연속성 판정가다. 샷 목록(시간순, 샷마다 LOCATIONuX   명시)과 씬 원문 전문을 받는다. 각 샷마다, 앞쪽 샷의 생성 이미지uN   한 장을 '배경(장소) 앵커' 참조 사진으로 붙일지 판정하라.uU   (a) prev: ★유일한 기준 = 배경 동일성. 두 샷이 사실상 같은 지점,u[   같은 카메라 공간(같은 방의 같은 구역, 같은 계단의 같은 위치 등)을uS   비추고, 앞 샷 이미지에 그 배경이 실제로 보일 때만 지정하라.u   다음은 전부 null 이다:uO     · 인물이 이동해 다른 지점이 된 경우 — 같은 건물이라도u[       계단→옥상, 마당→골목, 실외→실내, 방→거실은 다른 배경이다.uI     · 두 샷의 LOCATION 서술이 서로 다른 경우 (무조건 null).uZ     · 앞 샷이 얼굴 클로즈업·손 인서트 등이라 프레임에 배경이 거의uX       안 담겨 장소 앵커 구실을 못 하는 경우 — 이때는 그보다 앞의,uU       같은 배경이 넓게 보이는 샷으로 거슬러 지정하는 것은 허용.uD     · 같은 배경이라도 시간대(낮/밤 등)가 다른 경우.uW   ★스토리가 이어진다, 같은 사건이다, 같은 인물이 나온다는 것은u^   근거가 아니다 — 인물의 의상·자세 일관성은 별도 장치가 담당하므로uP   고려하지 마라. 배경이 거의 똑같은 곳이 아니면 무조건 null.uG   반드시 목록에서 자기보다 앞의 샷만 지정할 수 있다.uI   (b) usage_en: prev 가 있으면, 그 참조 사진을 '어떻게' 쓸지uS   명령문 영어 2~4문장으로 저작하라 — 반드시 두 축을 다 쓸 것:uV     · TAKE: 이어받을 것 — 장소의 룩·재질·조명, 지속되는 상태물,uU       움직일 수 없는 인물의 자세·위치, 인물의 의상 등 원문상 이u0       샷에도 그대로 존재해야 하는 것.uP     · EXCLUDE: 배제할 것 — 이 샷의 공간·프레임에 없어야 하는uS       가구·인물·소품, 앞 샷 전용의 순간 요소, 다른 서브공간의uR       요소. '배경(장소)만 쓰고 인물은 쓰지 말 것', '특정 물체는u-       지우고 쓸 것'처럼 구체적으로.uU   원문 근거로만 판단하고, 작품 고유명사 대신 일반 서술을 써라.uI   각 샷: shot, prev(태그|null), reason_ko(한 구절 — 배경 동일/u7   상이 근거), usage_en(prev 없으면 빈 문자열).objectFr   arraytypestringnull)shotprev	reason_kousage_en)r   additionalProperties
propertiesrequired)r   r   r   rb   c              3      K   | ]P  }d | dt         j                  d   t        |         d    dt         j                  d   t        |         d   z    R yw)u   [씬 ] scenesheadingr   textN)r!   DATAr`   )r   sis     r   r   zstage_prev2.<locals>.<genexpr>  s_      A6? t2affX&s2w/	:;2>
&&
3r7
#F
+	,6?s   AAr   r   r   r   
int_platescoversc              3      K   | ]P  }| d |      d    |v rd|    ndz   dt         j                  t        j                  |         d    z    R yw)z [LOCATION: r   z | sub-space: r4   z]
  r<   N)r!   r=   r>   )r   rP   r(   tag2gtag2rooms     r   r   zstage_prev2.<locals>.<genexpr>#  sv      = 8<! #\$uQx.456-.(]^HQK=)	D!&&#F+,
-	.7;s   AA	s38_prev2u   씬 원문 전문:
u   

샷 목록(시간순):
r   u   prev2 누락: r   u   prev2 위반: u    → prev2prev2_v2_bakz[prev2] z | r   N(   r   z    usage: d   )r   r   rw   r   r!   r>   r   r   r   updater$   r   llm
SystemExitr   r   r?   r~   r}   )r%   r   SYSSCHEMArP   	scene_ids
scenes_txtr&   r'   r*   p_	shots_txtresrQ   gotmissingpvr   r(   r   r   s                     @@@r   stage_prev2r      s5    )C %D
))  C@ 'e*(F!34$h/#X.	L0
 B-C DNE IF d3dq	!d34I A6?A AJ VVXF!'!12!1AAeHaK!12D\\E\r48G3DaQU3DQ\EE	LL#j/:/Q!Q[[./:;H,HAU)HQK    		 = 8<= =I %%S&zl2N+ &(C %(L
1Lb2f:r>LC
1/$Q!3,q$G/>'344VF^2T>QVVBZ166!9%<~aSbT:;;  ;;tDxx.!9#G}^DMKKdV5FC;0D/EFGj>K:t 4567	 A 4
 3E: 2/s*   J*1J/J4J:?J?	KKc                     t               } t        j                         }t        j                  |      }i }t        j                  t        j
                  gz   D ]3  }|j                  |j                  di       j                  |i              5 |d   D ci c]  }|d   |
 }}t        j                         }t        j                         }t        j                         }	i }
|	j                         D ]1  \  \  }}}|
j                  |t                     j                  |       3 i }| d   D ])  }|d   D ]  }t        j                  d|d    dz  ||<   ! + t!        j"                  t$              }|j                  di       }t&        j)                  d	d	
       |j                  d      }t        j                  D ci c]  }||   d   D ]  }||  }}}|j                  | d   D ci c]  }|t        j
                   c}       |rt+        |       D cg c]	  }||   |f }}nSt        j                  D cg c]  }||   d   D ]  }||f  c}}| d   D cg c]  }t        j
                  |f c}z   }|D ]M  \  }}t&        | dz  }|j-                         rt/        d| d       3t0        j2                  t1        j4                  |         }|j                  |i       }| j                  di       j                  |      xs i }|j                  d      xs |j                  dd      }|j                  d      xs |j                  dd      }|j                  d      xsG |t        j
                  k(  r2| j                  di       j                  |i       j                  dd      nd}|rJ|j                  |      xs i j                  d      }|j                  |      xs i j                  dd      } n&|j                  |      xs i j                  d      }d} d }!g g }#}"|	j                  t1        j4                  |      g       }$|$s9t7        |
j                  t1        j4                  |      d   t                           }$g }%|rlt&        | dz  j-                         rR|}!|%j9                  t        j:                  t&        | dz  f       |$D ]  }&|&|v s|"j9                  ||&   d            nJ|%j9                  t<        t>        | dz  f       |t        j
                  k7  r]d }'t        d| dft        d| dft        d| dft        j                  d| dffD ]  \  }(})|(|)z  j-                         s|(|)z  }' n n||   }'|%j9                  t        j@                  |'f       |$D ]  }&|&|v rB||&   \  })}*|*j-                         s |"j9                  |)       |%j9                  d|) d |*f       I|&|v sN||&   \  })}*|*j-                         sg|#j9                  |)       |%j9                  d!|) d"|*f        d#t        jB                  |      z   d$z   d%t        jD                  |d&          d'||   d(    d)|!rd*nd+z   g}+|!r:|+j9                  d,       | r'|+j9                  d-t        jD                  |       z          tG        | |g      },|,r |+j9                  d.jI                  |,             |+j9                  t        jJ                         |+j9                  tL               |r'|+j9                  d/t        jD                  |      z          |r'|+j9                  d0t        jD                  |      z          |r'|+j9                  d1t        jD                  |      z          |"r'|+j9                  d2d3jI                  |"      z   d4z          n|+j9                  d5       |+j9                  d6       d7jI                  |+      }-t!        jN                  d8| |-|%d9|:       ||!|!r| nd|!rd;nd<|-|%D .*cg c]X  \  }.}*|.tQ        |*      jS                  tQ        tT                    rtQ        |*jW                  tT                    n
tQ        |*      d=Z c}*}.d>||<   t!        jX                  t$        |       t/        d| d?||   d@    dA|! dB       P y c c}w c c}}w c c}w c c}w c c}}w c c}w c c}*}.w )CNr   r   r   r   r   plate_re   
still_metaTrY   r   r   r   z_nb2.pngz	[stills] z skip(exists)r1   r2   r3   r4   r5   r6   r7   r8   r   r   bg4_bg3_bg2_bg_u   CHARACTER REFERENCE — zN: the exact person appearing in this shot; match face, hair and build exactly.u   PROP REFERENCE — zU: the exact object appearing in this shot; match its look, material and wear exactly.u   Create ONE FINAL photorealistic live-action film still of the moment below — contemporary South Korea, 2026; all people are Korean unless stated. TIME OF DAY (lock): r;   z#SHOT TEXT (authoritative, Korean): r<   zLOCATION (lock): r   u,    The shot takes place here — the attached z+PREVIOUS SHOT STILL shows this exact place.z)LOCATION PHOTOGRAPH shows the exact spot.u1  THIS SHOT CONTINUES THE PREVIOUS SHOT: everything the attached still established — the place, its fixed features and wear, each person's clothing and state — persists. Any person in it who cannot move stays PRECISELY as photographed (body, pose, contact points, held objects); only the camera changes.ud   PREVIOUS STILL USAGE (follow exactly — what to take from the attached still and what to exclude): r   zMOVEMENT (follow exactly): u+   FIGURES — size & depth (follow exactly): uU   CARRIED STATE (persist exactly — must match the neighbouring shots of this scene): zzPEOPLE: the SHOT TEXT alone decides whether any person is visible in this shot. IF a person appears, they must be one of: r^   uK    — never anyone else, and never add a person the shot text does not show.z5No people appear unless the shot text itself says so.z6No text, captions, watermarks or annotations anywhere.rb   
s38_still_z16:9)aspect_ratiorl   u   prev 단독u#   경량콘티+플레이트+엔티티)labelpath)rf   	prev_used
prev_usageref_moderh   rj   u    완료 (mode=r  z, prev=r:   )-r   r   r   rn   r   r$   r   r?   r@   
_char_refs
_prop_refs_ve_idsr   rq   r   rr   r   r   r   OUTSrs   r   rp   r}   r!   r=   r>   r   r#   PREV_STILL_LABELLIGHT_PANEL_LABELr   PLATE_STILL_LABELrA   rB   rU   rw   REALIZE_STILLEXPRESSION_REALISMimg_nb2r`   
startswithro   relative_tor~   )/r%   r&   rC   prev_allr*   r'   r(   charspropsvescene_unionr   shiids	tag2plater   rP   r   metar   r   r)   rf   rF   rT   rG   rH   rI   r3   r6   rJ   prev_tagr  r  
char_names
prop_namesve_idsrj   cidplatepfx_dirnamepr   r   prompt_fulllabs/                                                  r   stage_stillsr$  >  s   
)CVVXF	
V	BHllakk]*

62.222r:; +!'!12!1AAeHaK!1D2LLNELLNE	
BK((*	S3r35)005 %I,HA55VBuI;d#;;IaL    ;;tD??<,DJJtdJ+HHWE\\E\r48G3DaQU3DQ\EE	LL#j/:/Q!Q[[./:;'<S'AB'A!q1'AB"#,, ,,Bb'*A Q* , ,),Z9AQ9: 	cuH%%::<IcU-01FF166#;FF3Oggj"%))#.4"77=)BQUU:r-B'','?155B+?'',' ,q{{" GGJ#''R044\2F(* 	 		#,"11&9H))C..B33JCJ S)/R44V<HJ	!#RJ
sR(KOOAFF3KNCEBCF8*H 55==? IKK++8*H 557 8%<%%eCjm4  KK*DcU$<,?@Aq{{"'*d3%t,<&='*d3%t,<&='*d3%t,<&='(uuC5o&>&@MGT  $..0 '$&@ "#KK,,e45%<#CjGD!xxz"))$/6tf =7 789%; < E\#CjGD!xxz"))$/1$ 8: :;<%> ? $E jjo !$$ 2!))AfI2F1GHT
: 67 8, ,  ="
 LL;< Fii
+,- 3&LL2'Q__%'(LL699X./ 0LLF99W-. /LL D99W-. / LL!%:!67''( LL % & " 	#kk%(			Jse$k4%	5 y(1*r*3C!
 $(	) $(a	  #"%a&"3"3CI">  #1==#67$'F- $(	)
S	 	
D$	#nT#Yz-B,C D k$ 	%K 1 3 F: C,9~)s+   c?c+cc!=c&c,2Ac1c                  N  #$%& dd l &t               } t        j                         }t	        j
                  t              }|d   D ci c]  }|d   |
 }}i }t        j                  t        j                  gz   D ]3  }|j                  |j                  di       j                  |i              5 t        dz  ##j                  dd       d %#&fd	$d
j                  %fd|d   j                         D              }d
}|j                  d      xs i j                         D ]@  \  }	}
|
j                  dd      }d
}dD ]i  }d| d|	 d|j                          d}|
j                  d      |k(  rdnd
}|d| d| d| d|
j                  di       j                  |d       d| dz  }k d
}|
j                  d      xs i j                         D ]!  \  }}|D ]  }|d| d  %|d!          d"z  } # |d#|	 d$ %t!        |
j                  d                   d%|
j                  d&      rd'nd( d) %|       d*| d+| d|	 d,| d|	 d- %|       d.|rd/| d0nd
z   d1z   z  }C |rd2|z   d3z   }g }|j                  d4i       }t        j                  D cg c]  }||   d5   D ]  }||f  c}}| d6   D cg c]  }t        j                  |f c}z   }d }d
}|D ]  \  }}	||k7  r<||j#                  |d3z          d7 %||   d8          d9| d: %||   d;          d1}|}|j                  |	i       }|j                  d<d      }|j                  d=      rd>nd?}d
j                  $%fd@|j                  dg       D              }|j                  dA      xs i j                  |	      xs |j                  |	      xs i }|j                  dB      xs |j                  dCd
      } d
}!|j                  dD      rdE %|dD          d1}!|d#|	 d| dF %t!        |j                  d      xs dG             |j                  d      rdH %|        dInd
z   dJ|! dK %t$        j&                  t%        j(                  |	         dL          dM|	 dN|	 dO|	 dP|	 dQz   |j                  d=      rdRndSz   dTt+        |j                  dg              dU %|       dV| dW %|j                  dXd
             dY	z   z  } ||j#                  |d3z          t-        dZ |j/                         D              }"t0        j3                  d[|" d\t+        |      |"z
   d]t+        |d          d^| d_| d`d
j                  |       da       t5        dbt0                y c c}w c c}}w c c}w )cNr   r   r   r   rj   TrY   c                 F    t        j                  t        | xs d            S )Nr4   )_htmlescaper`   )rP   s    r   esczstage_html.<locals>.esc  s    ||CRL))r   c                     | j                  d      s| S t        |       }|j                  z  }|j                         sj	                  ||       d|j                   S )N/zout/s38/refs/)r  r   r   rp   copy)path_ssrcdstREFDshutils      r   _relzstage_html.<locals>._rel  sT      %M6lSXXozz|KKS!sxxj))r   r4   c              3   r   K   | ].  \  }}d |d    d|d    d |       dt        |d          d	 0 yw)<figure><a href='out/s38/rg   z"' target=_blank><img src='out/s38/' loading=lazy></a><figcaption>r9   r   u   샷)</figcaption></figure>N)ru   )r   r   r   r)  s      r   r   zstage_html.<locals>.<genexpr>  s_      0
 /HD"	 $BvJ< 0ZL )4ykC7$4#5 6	 /s   47rX   plate_chainprefixbg3)ABrx   zout/s38/rd   re   selectedu
    ★선택z<figure class=pn2><a href='' target=_blank><img src='r5   totals?u   점</figcaption></figure>critiquez<li>[r   issue_koz</li>z<div class=shot><h3>u   <span class=k> — 합산 u    · 수정 fix_skippedu   생략(결함 0)u   적용u    · 계보 z</span></h3><div class=row>r4  z&.png' target=_blank><img src='out/s38/u;   .png' loading=lazy></a><figcaption><b>최종 플레이트 (z!)</b></figcaption></figure></div>u1   <details><summary>VLM 결함 목록</summary><ul>z</ul></details>z</div>uK  <section><h2>실외 플레이트 — s29 풀 체인 (3롤 → GPT/Gemini 합산 판정[마스터 일치·지역 사실성 축] → 결함 취합 수정)</h2><div class=note>마스터=<a href='out/forest_map/top2/top2_photo_fixed_nb2.png' target=_blank style='color:#9ecbff'>s29 top2 최종본</a> (45도 항공 전체 부지)</div>z
</section>r   r   r   z<section><h2>name_koz <span class=k>(z,)</span></h2><div class=note>LOCATION lock: r   r  r  u!   <span class=on>prev 단독</span>u*   <span class=off>콘티+플레이트</span>c              3      K   | ]K  }d  |d          d |d          d |d   j                  d      d   j                                d M yw)	z<figure class=pn><a href='r   r<  r5  r   u   —r   r@  N)splitstrip)r   r   r2  r)  s     r   r   zstage_html.<locals>.<genexpr>>  sr      )
 (	 )ai(9 :ai) *qz//6q9??ABC$& (s   AAr   r   reasonr  u   <div class=note>사용 지시: u    <span class=k> — prev 판정: u   없음r9   r:   z</span></h3>z<div class=note>r<   z5</div><div class=row><figure><a href='out/s38/stills/z1_nb2.png' target=_blank><img src='out/s38/stills/uq   _nb2.png' loading=lazy></a><figcaption>nb2 스틸</figcaption></figure><figure class=pn2><a href='out/s38/panels/z-.png' target=_blank><img src='out/s38/panels/u7   .png' loading=lazy></a><figcaption>경량 콘티 패널u&    (스틸엔 미사용 — prev 단독)u    (참조로 사용)u>   </figcaption></figure><div class=refs><div class=note>참조 (u	   장) — z</div><div class=refrow>uF   </div></div></div><details><summary>프롬프트 전문</summary><pre>rh   z</pre></details></div>c              3   D   K   | ]  }|j                  d       sd  yw)r  r0   N)r?   )r   rH   s     r   r   zstage_html.<locals>.<genexpr>c  s     @MqQUU;-?Ms     uD  <!DOCTYPE html>
<html lang=ko><head><meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>s38 — 옥탑 23샷: 경량 콘티 + prev 단독 참조</title>
<style>
body { margin:0; padding:24px; background:#0f1216; color:#e6e6e6;
       font:14px/1.6 -apple-system,'Apple SD Gothic Neo',sans-serif; }
h1 { font-size:20px; } h2 { font-size:17px; margin:34px 0 8px;
     border-bottom:1px solid #333; padding-bottom:5px; }
h3 { font-size:15px; margin:6px 0; }
.k { color:#8a939e; font-size:13px; font-weight:400; }
.row { display:flex; gap:14px; align-items:flex-start; margin:10px 0;
        flex-wrap:wrap; }
figure { margin:0; max-width:620px; }
figcaption { color:#c9d2dc; font-size:12.5px; }
img { max-width:620px; width:100%; border-radius:8px;
      border:1px solid #2a2f36; }
figure.pn2 { max-width:300px; } figure.pn2 img { max-width:300px; }
figure.pn2 figcaption { font-size:11px; }
.note { color:#8a939e; }
.box { background:#161b22; border:1px solid #2a2f36; border-radius:8px;
       padding:12px 16px; margin:12px 0; }
.shot { border-top:1px dashed #2a2f36; padding:12px 0; }
.on { background:#1e3a2a; color:#7ee2a8; border-radius:5px;
      padding:1px 8px; font-size:12px; margin-left:6px; }
.off { background:#3a2a1e; color:#e2b57e; border-radius:5px;
       padding:1px 8px; font-size:12px; margin-left:6px; }
.refs { max-width:640px; }
.refrow { display:flex; gap:8px; flex-wrap:wrap; }
figure.pn { max-width:150px; } figure.pn img { max-width:150px; }
figure.pn figcaption { font-size:11px; max-width:150px; }
details { margin:6px 0; } summary { color:#9ecbff; cursor:pointer; }
pre { background:#161b22; border:1px solid #2a2f36; padding:10px;
      white-space:pre-wrap; font-size:12px; }
</style></head><body>
<h1>s38 — 옥탑 23샷: 경량 레이아웃 콘티 + prev 단독 참조 스틸
(prev u    / 콘티+플레이트 u  )</h1>
<div class=box>x_quad v1~v3·체이닝 실험 종합 규칙(사용자 확정, prev 판정
v3 — 배경 동일성 유일 기준):
①콘티=<b>초경량 레이아웃 선화</b>(얇은 윤곽선만 — 질감 오염 방지)
②스틸 참조: <b>prev(배경이 사실상 같은 지점인 이전샷만 — 이동·장소
상이·클로즈업 배경 부재·시간대 상이는 전부 제외) 있으면 이전샷 실사
오롯이 하나만</b>(자세·장소·의상·소품 잠금 — 콘티·플레이트·엔티티
제외) / 없으면 경량 콘티 패널+<b>배경 플레이트</b>+캐릭터·소품.
③자세 정본·carried state·중의어 교정본은 전 샷 텍스트 안전망.
이전 판 비교:
<a href='s37_rooftop_rebuild.html' style='color:#9ecbff'>s37 갤러리</a>
· <a href='x_quad_gallery.html' style='color:#9ecbff'>4분할 실험</a></div>
<section><h2>경량 콘티 시트 (u   장)</h2>
<div class=row>z</div></section>
r   z
</body></html>z[html] )r1  r   r   r   r   r   r   r   r$   r   r?   rr   rs   rw   r   lowerr`   r#   r!   r=   r>   ru   r   valuesPAGE
write_textr}   )'r%   r&   r   r'   r(   r  r*   sheets_html
plate_htmlrF   recpfxcandsr#  relselmarkissuesrH   itsr+   secsr  rP   ordercurbodyrf   mtmodebadge	ref_itemspjrH  
usage_htmln_prevr0  r2  r)  r1  s'                                      @@@@r   
stage_htmlrb    s   
)CVVXF;;tD!'!12!1AAeHaK!1D2Hllakk]*

62.222r:; +<DJJtdJ+** '' 0
 X,,.0 0K JXXm,299;Sggh&"CSE3%qT:C&)ggj&9S&@lbG3C5 9##&% (%%(E#''(B/33C=>c'.	0 1E # wwz*0b779FAsE!Bs1Z='9&:%@@  : 	"3%(S1B-C)D(E0F,HU#c(#>ug'uAcU 3!!$Qse ,336s8* = &, C6( "13	5 
	
 <6 2
 5??
 BNN 	 D88L"%D || )|2hw' !W' | )%(_
5_AKK_
56E CD	c3;D</0#CT
9(=$>#?&tf -DJz234F<D CXXc2vvj#&8:{8K4B 	GG )
 VVFB') )	 hhw%2**3/J8<<3DJ$<x(<
66,!"\"234F<J"3%qCv2(3457 ')ffVnCK=""> ZLs166!&&+#6v#>?@ A//2e 477:e <99< >77:e <AB	B <>66+;N7)+RVVFB'()3t9+ >!!* ,x,-..DFF	G3 ^ D<'(@DKKM@@FOO $H h%c$i&&8%9 :$ %(X$7#8 9}   g4 4j 
GD6
] 3B)
5s   VV<V"__main__z--onlyT)contir   r   r   html)r   choices)F)/__doc__argparsere  r'  syspathlibr   __file__parentro   r   insertr`   
forest_libr   s35_fullrunr!   s37_rooftop_rebuildr   s34_stillrunr@   rr   r   r  rL  r   rw   rv   r  r	  r   r.   rL   rU   r   r   r   r   r$  rb  __name__ArgumentParserapadd_argument
parse_argsaonlyr   r   r   <module>ry     sS     
 H~ 3t9     eellU
X~
X~((ii   YY      8'T/d)V8re%Psl z	 	 	 	"BOOHtH  J
A9k:Z1129 ; r   