
    jPC                        d Z ddlmZ ddlZddlZddlmZ  ee      j                         j                  Z
e
dz  Ze
j                  d   Zedz  dz  Zed	z  d
z  dz  ZddZddZddZddZddZedk(  r e        yy)zBRender the audited chain data as a one-row-per-chain review table.    )annotationsN)Pathzchain-audit-2026-08-21.json   reportsz,2026-08-21-chain-catalog-domestic-audit.htmlz.runtimezchain-catalog-reviewz
index.htmlc                B    t        j                  t        |       d      S )NT)quote)htmlescapestr)values    6.runtime/chain-catalog-data/render_chain_audit_html.pyescr      s    ;;s5z..    c                    | j                  d      ryd| v ry| j                  d      ry| j                  d      ry| j                  d	      ry
y)Nu   복수multiu   1곳 +zone-internalu   국내 부자재 판매처 1곳oneu   사내internal	   완제품finishedmissing)
startswith)statuss    r   status_classr      sU    "6:;"%r   c                
   | j                  di       }|j                  dd      }|rdnd}|rdnd}| d   d	k(  rd
nd}dt        | d          dt        | d          dt        | d          d| d| d| dt        | d          dS )Nverification	reachableFu	   확인됨u   접속 실패zlink-okz	link-faillisting_typerawu	   부자재r   z<li>
      <a href="urlz=" target="_blank" rel="noopener noreferrer">
        <strong>sellerua   </strong><span class="external" aria-hidden="true">↗</span>
      </a>
      <span class="kind ">z&</span>
      <span class="link-state z</span>
      <small>titlez</small>
    </li>)getr   )listingr   r   badgecsskinds         r   listing_markupr(   $   s    ;;~r2L  e4I$K/E )kC!.1U:;DGEN#$ %WX&'( )W^456b ?"e2eW -''"#$ %
 r   c                F   dj                  d | d   D              }|sd}dj                  d | d   D              }|sd}g }| d   r|j                  d	| d    d
       | d   r|j                  d       |s|j                  d       | d   rdj                  | d         nd}dj                  | d         }t        | d         }dj                  | d   | d   z         }dj                  | d   |||dj                  | d         | d   g      }d| dt        |j	                                d| d   ddt        | d          dt        |       dt        | d          d t        |       d!| d"t        | d          d#t        | d$          d%| d&| d'dj                  |       d(S ))N c              3  2   K   | ]  }t        |        y wN)r(   ).0items     r   	<genexpr>zrender_row.<locals>.<genexpr>5   s     W~d+W   representative_listingsuE   <li class="none">현재 확인된 공개 상품 페이지 없음</li>c              3  :   K   | ]  }d t        |       d  yw)z<span class='supplier'>z</span>Nr   )r-   names     r   r/   zrender_row.<locals>.<genexpr>8   s     p1#d)GDps   internal_supplier_namesu'   <span class="none-inline">없음</span>internal_supplier_record_countu,   <span class='evidence'>POM 공급처 기록 u
   건</span>chainbook_evidenceu*   <span class='evidence'>TN 체인북</span>u'   <span class='none-inline'>없음</span>aliasesz / u   —u    · searched_termsr    public_raw_sellerspublic_finished_sellersr4   z<tr data-status="z" data-search="z">
      <td class="number">index02dz2</td>
      <td class="identity">
        <strong>z(</strong>
        <span class="aliases">u,   </span>
        <details><summary>검색어 u   개</summary><small>zW</small></details>
      </td>
      <td class="decision">
        <span class="status r!   z</span>
        <strong>recommendationz5</strong>
      </td>
      <td><ul class="listings">z,</ul></td>
      <td><div class="suppliers">z-</div></td>
      <td><div class="evidences">u   </div></td>
      <td class="rights">판매처 자산 비복제<br><small>독자 촬영·별도 생성 이미지만 사용</small></td>
    </tr>)joinappendr   r   lowerlen)	rowlistings	suppliersr   r8   termsr&   seller_namessearch_blobs	            r   
render_rowrJ   4   s   wwW<U8VWWHZpQTUnQoppI=	H
+,FsKkGlFmmwxy
 DEAB,/	NejjY(GKK,-.E
s8}
%C88C 45<U8VVWL((CK%sxxPSTmPnGoqtu}q~  AK _S9J9J9L5M4N Og,s+ ,S[!" #"7|n -%%(-=)>%?$@@TUXY^U_T` a !ECH$6#7 8S)*+, -  (z *""+ -""$''("3!4 5
 r   c                 T   t        j                  t        j                  d            } | d   }t	        d |D              }t	        d |D              }t	        d |D              }t	        d |D              }t	        d |D              }t	        d	 |D              }d
j                  d |D              }dj                  d | d   j                         D              }	d| d| d| d   d    d| d   d    d| d| d| d| d||z    d|	 d| d| d| d}
t        j                  j                  d d !       t        j                  j                  d d !       t        j                  |
d       t        j                  |
d       t        d"t                t        d"t                y )#Nzutf-8)encodingrowsc              3  8   K   | ]  }t        |d            yw)r;   Nboolr-   rD   s     r   r/   zmain.<locals>.<genexpr>\   s     DD123Ds   c              3  >   K   | ]  }t        |d          dk\    yw)r;      NrC   rQ   s     r   r/   zmain.<locals>.<genexpr>]   s      Jcc#2349J   c              3  >   K   | ]  }t        |d          dk(    yw)r;   r   NrT   rQ   s     r   r/   zmain.<locals>.<genexpr>^   s      HCC012a7HrU   c              3  H   K   | ]  }|d     xr t        |d           yw)r;   r5   NrO   rQ   s     r   r/   zmain.<locals>.<genexpr>_   s-     ocfC 455^$sC\?]:^^o    "c              3  X   K   | ]"  }|d     xr |d    xr t        |d          $ ywr;   r5   r<   NrO   rQ   s     r   r/   zmain.<locals>.<genexpr>`   s\       W  KNC 455  FcB[>\:\  Faefi  kD  gE  bF  F  Ws   (*c              3  H   K   | ]  }|d     xr |d    xr |d      ywrZ    rQ   s     r   r/   zmain.<locals>.<genexpr>a   sD       O  CFc.//}<U8V4V}_bc|_}[}}  OrX   
c              3  2   K   | ]  }t        |        y wr,   )rJ   rQ   s     r   r/   zmain.<locals>.<genexpr>b   s     ;s:c?;r0   r*   c              3  H   K   | ]  \  }}d t        |       d|dd  yw)z<li><strong>z</strong><span>,u   개 상품 대조</span></li>Nr3   )r-   r4   counts      r   r/   zmain.<locals>.<genexpr>c   s2      D% s4ykq	9VWrX   catalog_scopeu7  <!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="color-scheme" content="light">
  <title>TN 체인 국내 조달 전수조사</title>
  <style>
    :root{--ink:#233033;--ink-soft:#51626a;--muted:#75898f;--bg:#eef4f5;--surface:#f8fbfb;--line:#d9e4e6;--accent:#1f8a99;--accent-soft:#d8ecef;--good:#2f8f7a;--warn:#a66f24;--bad:#aa4c60;--info:#496c91;--page-bg:#e1eaeb;--font:"Pretendard","Apple SD Gothic Neo","Malgun Gothic",system-ui,-apple-system,sans-serif;--shadow:0 12px 40px rgba(35,48,51,.08)}
    *{box-sizing:border-box} html{scroll-behavior:smooth} body{margin:0;min-width:320px;background:var(--bg);color:var(--ink);font-family:var(--font);line-height:1.55} a{color:inherit} button,input,select{font:inherit} button:focus-visible,input:focus-visible,select:focus-visible,a:focus-visible,summary:focus-visible{outline:3px solid rgba(31,138,153,.3);outline-offset:2px}
    .page{width:min(1680px,calc(100% - 40px));margin:0 auto;padding:36px 0 72px} .masthead{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:24px;align-items:end;padding-bottom:24px;border-bottom:1px solid var(--line)} .eyebrow{margin:0 0 6px;color:var(--accent);font-size:12px;font-weight:800;letter-spacing:.12em;text-transform:uppercase} h1{margin:0;font-size:clamp(30px,4vw,52px);line-height:1.06;letter-spacing:-.045em} .lead{max-width:920px;margin:14px 0 0;color:var(--ink-soft);font-size:15px} .meta{color:var(--ink-soft);font-size:12px;text-align:right} .meta strong{display:block;color:var(--ink);font-size:14px}
    .stats{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:8px;margin:18px 0} .stat{padding:13px 14px;border:1px solid var(--line);border-radius:10px;background:var(--surface)} .stat strong{display:block;font-size:27px;line-height:1.1} .stat span{display:block;margin-top:4px;color:var(--ink-soft);font-size:12px} .stat.good strong{color:var(--good)} .stat.warn strong{color:var(--warn)} .stat.bad strong{color:var(--bad)}
    .finding{display:grid;grid-template-columns:1.25fr .75fr;gap:12px;margin-bottom:14px} .card{padding:16px 18px;border:1px solid var(--line);border-radius:12px;background:var(--surface)} .card h2{margin:0 0 7px;font-size:17px} .card p{margin:0;color:var(--ink-soft);font-size:13px} .card strong{color:var(--ink)} .source-list{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px;margin:11px 0 0;padding:0;list-style:none} .source-list li{padding:8px;border-radius:7px;background:var(--bg)} .source-list strong,.source-list span{display:block;font-size:11px} .source-list span{color:var(--muted)}
    .controls{position:sticky;z-index:10;top:8px;display:grid;grid-template-columns:minmax(260px,1.4fr) minmax(230px,.7fr) auto;gap:8px;margin:14px 0 10px;padding:9px;border:1px solid var(--line);border-radius:12px;background:rgba(248,251,251,.95);box-shadow:var(--shadow);backdrop-filter:blur(12px)} input,select,button{min-height:43px;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--ink);padding:9px 11px} button{cursor:pointer} .visible-count{display:flex;align-items:center;justify-content:flex-end;min-width:120px;color:var(--ink-soft);font-size:13px} .visible-count strong{margin-right:3px;color:var(--ink);font-size:18px}
    .table-wrap{overflow:auto;border:1px solid var(--line);border-radius:12px;background:var(--surface);box-shadow:var(--shadow)} table{width:100%;min-width:1430px;border-collapse:separate;border-spacing:0;table-layout:fixed;font-size:12.5px} col.no{width:48px} col.identity{width:210px} col.decision{width:210px} col.public{width:390px} col.internal{width:170px} col.evidence{width:170px} col.rights{width:180px} thead th{position:sticky;z-index:2;top:0;padding:11px 10px;border-bottom:1px solid var(--line);background:#edf5f6;color:var(--ink-soft);text-align:left;font-size:11px} tbody td{vertical-align:top;padding:12px 10px;border-bottom:1px solid var(--line)} tbody tr:last-child td{border-bottom:0} tbody tr:hover{background:#f2f8f8} tr[hidden]{display:none} .number{color:var(--muted);font-variant-numeric:tabular-nums} .identity>strong{display:block;font-size:14px} .aliases{display:block;margin-top:3px;color:var(--ink-soft)} details{margin-top:7px;color:var(--muted)} summary{cursor:pointer;font-size:11px} details small{display:block;margin-top:4px;line-height:1.4} .decision>strong{display:block;margin-top:6px;font-size:12px}
    .status,.kind,.link-state,.supplier,.evidence{display:inline-flex;align-items:center;border-radius:999px;padding:3px 7px;font-size:10.5px;line-height:1.25} .status.multi{background:#dcefe8;color:#246b58} .status.one-internal{background:#e3eef5;color:#3e6680} .status.one{background:#fff0d8;color:#875b1e} .status.internal{background:#ece7f5;color:#685181} .status.finished{background:#eceff1;color:#59676d} .status.missing{background:#f7e3e7;color:#93485b} .listings{display:grid;gap:10px;margin:0;padding:0;list-style:none} .listings li{position:relative;padding-left:10px;border-left:2px solid var(--line)} .listings a{text-decoration:none} .listings a:hover strong{text-decoration:underline} .listings small{display:block;margin-top:3px;color:var(--ink-soft);line-height:1.35} .external{margin-left:3px;color:var(--accent)} .kind{margin-left:6px;background:var(--accent-soft);color:#346c74} .kind.finished{background:#eceff1;color:#59676d} .link-state{margin-left:3px;padding:2px 5px} .link-ok{color:var(--good)} .link-fail{color:var(--bad)} .none,.none-inline{color:var(--muted)} .suppliers,.evidences{display:flex;flex-wrap:wrap;gap:5px} .supplier{background:#e7edf4;color:#425d79} .evidence{background:#edf0ec;color:#586259} .rights{color:var(--ink-soft)} .rights small{color:var(--muted)}
    .notes{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px} .notes h2{margin:0 0 6px;font-size:15px} .notes p,.notes li{font-size:12px;color:var(--ink-soft)} .notes ul{margin:0;padding-left:18px} .raw-link{display:inline-flex;margin-top:10px;color:var(--accent);font-weight:700;text-decoration:none}
    @media(max-width:900px){.page{width:min(100% - 20px,1680px);padding-top:22px}.masthead,.finding{grid-template-columns:1fr}.meta{text-align:left}.stats{grid-template-columns:repeat(2,minmax(0,1fr))}.source-list{grid-template-columns:repeat(2,minmax(0,1fr))}.controls{position:static;grid-template-columns:1fr}.visible-count{justify-content:flex-start}.notes{grid-template-columns:1fr}.table-wrap{margin:0 -10px;border-radius:0;border-left:0;border-right:0}}
    @media print{@page{size:A4 portrait;margin:10mm}body{background:#fff;font-size:9pt}.page{width:100%;padding:0}.controls{display:none}.stats{grid-template-columns:repeat(3,1fr)}.finding{grid-template-columns:1fr}.table-wrap{overflow:visible;border:0;box-shadow:none}table{min-width:0;font-size:7pt;table-layout:auto}thead th{position:static}tbody tr{break-inside:avoid}.notes,.card,.stat{break-inside:avoid}}
  </style>
</head>
<body>
<main class="page">
  <header class="masthead">
    <div><p class="eyebrow">TN Silver · 국내 조달 조사</p><h1>체인 후보 77개 전수조사</h1><p class="lead"><strong>결론:</strong> 국내 부자재 상품 페이지가 확인된 체인은 u   개이며, 그중 u   개는 복수 판매처에서 확인됐다. POM과 체인북은 판매처 수에서 제외했고, POM은 실제 공급처명만 별도 표시했다.</p></div>
    <p class="meta"><strong>조사일 2026-08-21</strong>직접 링크 link_verificationunique_urlsu   개 · 접속 성공 r   u   개</p>
  </header>
  <section class="stats" aria-label="조사 요약">
    <div class="stat"><strong>77</strong><span>전체 체인 후보</span></div><div class="stat good"><strong>uY   </strong><span>국내 부자재 판매 확인</span></div><div class="stat good"><strong>uR   </strong><span>복수 판매처 확인</span></div><div class="stat warn"><strong>uS   </strong><span>부자재 판매처 1곳</span></div><div class="stat warn"><strong>uT   </strong><span>사내 공급처만 확인</span></div><div class="stat bad"><strong>u  </strong><span>부자재 조달 미확인</span></div>
  </section>
  <section class="finding">
    <article class="card"><h2>판정 기준</h2><p><strong>판매처는 실제 국내 업체의 체인 부자재 상품 페이지가 있을 때만 셌다.</strong> POM은 데이터 저장소이고 체인북은 사내 참고자료이므로 판매처가 아니다. 완제품에서만 이름이 확인된 경우도 부자재 판매처로 세지 않았다.</p><ul class="source-list">ur  </ul></article>
    <article class="card"><h2>게시 자산 원칙</h2><p><strong>판매처 수와 관계없이 해당 사이트의 사진·설명·상품코드·카탈로그 배열은 복제하지 않는다.</strong> 체인 이름과 구조 확인에만 참고하고, 공개용 이미지는 TN의 독자 촬영 또는 별도 생성본을 사용한다. 단일 판매처 명칭은 일반 체인명인지 한 번 더 검토한다.</p></article>
  </section>
  <div class="controls" aria-label="표 필터">
    <input id="query" type="search" placeholder="체인명·별칭·판매처·사내 공급처 검색" aria-label="체인 검색">
    <select id="status" aria-label="조달 상태"><option value="all">모든 상태</option><option value="multi">복수 국내 판매처</option><option value="one-internal">판매처 1곳 + 사내 공급처</option><option value="one">국내 판매처 1곳</option><option value="internal">사내 공급처만</option><option value="finished">완제품 판매만</option><option value="missing">조달 근거 미확인</option></select>
    <div class="visible-count"><strong id="visible">77</strong> / 77개 표시</div>
  </div>
  <div class="table-wrap" tabindex="0" aria-label="체인별 조사 결과 표">
    <table><colgroup><col class="no"><col class="identity"><col class="decision"><col class="public"><col class="internal"><col class="evidence"><col class="rights"></colgroup>
      <thead><tr><th>No.</th><th>체인명 · 별칭</th><th>판정</th><th>국내 판매처 · 직접 상품</th><th>사내 실제 공급처</th><th>내부 근거</th><th>게시 시 처리</th></tr></thead>
      <tbody>u   </tbody>
    </table>
  </div>
  <section class="notes">
    <article class="card"><h2>이번 조사로 말할 수 있는 것</h2><ul><li>uW   개는 조사일 현재 국내 체인 부자재 상품 페이지가 열렸다.</li><li>u  개는 공개 판매 페이지 없이 POM의 실제 공급처 기록만 확인됐다.</li><li>동일 업체의 소매몰·도매몰·입점몰은 독립 판매처로 중복 계산하지 않았다.</li></ul></article>
    <article class="card"><h2>이번 조사로 말할 수 없는 것</h2><ul><li>로그인 이후 재고, 전화 주문, 최소수량과 실제 납기는 공개 페이지로 확정하지 않았다.</li><li>검색 결과가 없다는 것은 국내에 제품이 없다는 뜻이 아니라 공개 조달 근거를 찾지 못했다는 뜻이다.</li><li>단일 판매처 상품명이 업계 일반명인지 판매처 고유명인지는 이미지 제작 전에 최종 확인이 필요하다.</li></ul><a class="raw-link" href="/.runtime/chain-catalog-data/chain-audit-2026-08-21.json">JSON 원자료 보기 →</a></article>
  </section>
</main>
<script>
  const query=document.querySelector('#query');const status=document.querySelector('#status');const rows=[...document.querySelectorAll('tbody tr')];const visible=document.querySelector('#visible');
  function filter(){const term=query.value.trim().toLowerCase();const state=status.value;let count=0;for(const row of rows){const show=(!term||row.dataset.search.includes(term))&&(state==='all'||row.dataset.status===state);row.hidden=!show;if(show)count++}visible.textContent=count}
  query.addEventListener('input',filter);status.addEventListener('change',filter);
</script>
</body>
</html>T)parentsexist_okzwrote )jsonloads	DATA_PATH	read_textsumr@   itemsOUTPUTparentmkdirPREVIEW
write_textprint)datarM   	raw_countmulti_count	one_countinternal_onlyfinished_onlyr   
table_rowssource_cardsdocuments              r   mainr|   Y   s   ::i))7);<D<DDtDDIJTJJKH4HHIojnooM  W  RV  W  WM  O  JN  O  OG;d;;J77 0668 LM0 NW  MX  Xj  kv  jw wHHLM`HaboHpGq  rG  HL  M`  Ha  bm  Hn  Go op qzoz  {T  U`  Ta  as  t}  s~  ~Q  R_  Q`  `t  u|  L  uL  tM M} ~J  }K K \ R S\Q\  ]t  uB  tC 
C]8Hr MMt4NN5
h1x'2	F6(
	F7)
r   __main__)returnr   )r   r   r~   r   )r$   dictr~   r   )rD   r   r~   r   )r~   None)__doc__
__future__r   r	   rg   pathlibr   __file__resolvern   HEREri   re   PROJECTrm   rp   r   r   r(   rJ   r|   __name__r\   r   r   <module>r      s    H "    H~&&00	
,,q/	9	M	M
J
!7
7,
F/ "JL^ zF r   