/* =============================================================
   Cight 단초점렌즈 가격 비교표 — 메인
   5단 카테고리(STEP 5→1)를 한 장에. 맨 왼쪽이 가장 이상적인 설계.
   제품마다 첨부 가능한 사진(image-slot) + 굴절률별(1.60/1.67/1.74) 가격.
   안경+렌즈 / 렌즈만 / 난시 / 처방 구분 토글.
   ============================================================= */
const { TABLES:CMP_T, PRODUCTS:CMP_P, INDICES:CMP_IDX, STEP_META:CMP_STEP } = window;

const cwon = (n)=> (n==null ? '' : n.toLocaleString('ko-KR'));

// intake.cight.co.kr 접수 이름 — ?name=김종관 또는 localStorage('cight_name')
const CMP_NAME = (()=>{ try{
  const p = new URLSearchParams(location.search).get('name');
  return (p || localStorage.getItem('cight_name') || '').trim();
}catch(e){ return ''; } })();

// os.cight.co.kr 도수 데이터 → 맞춤 추천 (rx.js)
const CMP_RX = (typeof window.CIGHT_parseRx === 'function') ? window.CIGHT_parseRx() : null;
if (CMP_RX && !CMP_RX.name && CMP_NAME) CMP_RX.name = CMP_NAME;
const CMP_TITLE_NAME = CMP_NAME || (CMP_RX && CMP_RX.name) || '';

// ===== 다국어 =====
const CMP_LANG0 = (()=>{ try{
  const p = new URLSearchParams(location.search).get('lang');
  const v = (p || localStorage.getItem('cight_lang') || 'ko');
  return (window.CIGHT_I18N && window.CIGHT_I18N[v]) ? v : 'ko';
}catch(e){ return 'ko'; } })();
const L_ = (lang)=> (window.CIGHT_I18N && window.CIGHT_I18N[lang]) || (window.CIGHT_I18N && window.CIGHT_I18N.ko) || {};
const tpl = (s,o)=> (s||'').replace(/\{(\w+)\}/g, (_,k)=> (o&&o[k]!=null)?o[k]:'');
const prodTr = (lang,key)=> (lang!=='ko' && window.CIGHT_PROD && window.CIGHT_PROD[lang] && window.CIGHT_PROD[lang][key]) || null;
const honor = { ko:'님', ja:'様', en:'', zh:'' };
const INLINE = {
  emptyCol: { ko:'해당 구분 없음', en:'None', ja:'該当なし', zh:'无' },
  upgrade:  { ko:'업그레이드', en:'Upgrade', ja:'アップグレード', zh:'升级' },
  heroA:    { ko:'가장자리까지 선명', en:'Sharp to the edge', ja:'端まで鮮明', zh:'边缘也清晰' },
  heroB:    { ko:'어느 방향에서도 또렷한 시야', en:'Clear vision in any direction', ja:'どの方向でも明瞭', zh:'各方向都清晰' },
  photo:    { ko:'제품 사진', en:'Product photo', ja:'製品写真', zh:'产品照片' }
};
const il = (k,lang)=> (INLINE[k] && (INLINE[k][lang]||INLINE[k].ko)) || '';

function CMP_LangSwitch({ lang, setLang }){
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  const cur = window.CIGHT_LANGS.find(l=>l.id===lang) || window.CIGHT_LANGS[0];
  React.useEffect(()=>{
    if(!open) return;
    const onDoc = (e)=>{ if(ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e)=>{ if(e.key==='Escape') setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    return ()=>{ document.removeEventListener('mousedown', onDoc); document.removeEventListener('keydown', onKey); };
  }, [open]);
  return (
    <div className={"cmp-lang"+(open?" open":"")} ref={ref}>
      <button type="button" className="cmp-lang-trigger" aria-haspopup="listbox" aria-expanded={open} onClick={()=>setOpen(o=>!o)}>
        <svg className="cmp-lang-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3c2.6 2.4 4 5.6 4 9s-1.4 6.6-4 9c-2.6-2.4-4-5.6-4-9s1.4-6.6 4-9z"/></svg>
        <span className="cmp-lang-flag">{cur.flag}</span>
        <span className="cmp-lang-cur">{cur.native}</span>
        <svg className="cmp-lang-chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
      </button>
      {open && (
        <ul className="cmp-lang-menu" role="listbox">
          {window.CIGHT_LANGS.map(l=>(
            <li key={l.id} role="option" aria-selected={lang===l.id} className={"cmp-lang-opt"+(lang===l.id?" on":"")} onClick={()=>{ setLang(l.id); setOpen(false); }}>
              <span className="cmp-lang-flag">{l.flag}</span>
              <span className="cmp-lang-name">{l.native}</span>
              {lang===l.id && <svg className="cmp-lang-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M5 12l5 5L20 7"/></svg>}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

// 접수 고객 목록 — window.CIGHT_CUSTOMERS / localStorage('cight_customers')
const CMP_CUSTOMERS = (()=>{
  let raw = null;
  try{
    raw = window.CIGHT_CUSTOMERS || null;
    if(!raw){ const ls = localStorage.getItem('cight_customers'); if(ls) raw = JSON.parse(ls); }
  }catch(e){ raw = null; }
  if(!Array.isArray(raw)) return [];
  const norm = window.CIGHT_normRx || ((x)=>x);
  return raw.map((c, i)=>{ const r = norm(c) || {}; r.id = (c && c.id!=null) ? c.id : (r.name? r.name+'_'+i : 'c'+i); return r; })
            .filter(r=> r && (r.name || r.od || r.os));
})();

const CMP_TIERS = [
  { id:"LENS", label:"렌즈만",   desc:"렌즈만 구입" },
  { id:"일반", label:"안경+렌즈", desc:"안경 구입 시" },
  { id:"STRX", label:"난시",     desc:"난시 특화" },
  { id:"RX",   label:"처방",     desc:"맞춤 처방" },
];

// 5단 정의 — 왼쪽(STEP 5)이 가장 이상적 · 오른쪽(STEP 1)이 경제형
const CMP_COLS = [
  { step:5, cls:"premium", ribbon:true, cat:"astig" },
  { step:4, cls:"", cat:"astig" },
  { step:3, cls:"", cat:"astig" },
  { step:2, cls:"", cat:"myopia" },
  { step:1, cls:"value", cat:"power" },
];

// 비교표 전용 STEP 라벨 (data.js STEP_META를 이 화면에서만 덮어씀)
const CMP_STEP_LABELS = {
  5:{ label:"STEP 5", name:"개인 맞춤", note:"+ 얼굴형 · 시습관까지 맞춤" },
  4:{ label:"STEP 4", name:"맞춤형", note:"개인 데이터 기반 설계" },
  3:{ label:"STEP 3", name:"양면 비구면", note:"왜곡 최소 · 미용 최적" },
  2:{ label:"STEP 2", name:"비구면", note:"얇고 또렷하게" },
  1:{ label:"STEP 1", name:"구면", note:"기본 · 경제형" },
};

// 비교표 전용 제품 재분류 — CLEARVIEW · FULL CONTROL을 STEP 2(비구면)로, REINS+를 STEP 4(맞춤형)로
const CMP_RECLASS = { clearview_fc: 2, reins: 4 };

// 비교표 전용 제품명 교체 — BRIDGE를 HI-VISION으로
const CMP_PROD_OVR = {
  bridge: { name:"HI-VISION", kr:"구면" },
};

// 업그레이드(SMARTLIFE) — 같은 STEP의 SEEMAX 상위 버전. 눈부심·빛번짐 감소로 야간·운전 특화
const CMP_UPGRADE = { smartlife_ind:true, smartlife:true };

// 니콘(Nikon Lenswear) 브랜드 제품 — 사진 위에 니콘 로고 배지 표시
const CMP_NIKON = { seemax_inf:true, seemax_ap:true, myopsee:true, bluv:true, bluv_fc:true };

function CMP_Card({ row, cls, up, rec, recIdx, lang, step, tier }){
  const base = CMP_P[row.k] || { name:row.k, kr:"", feat:[] };
  const p = Object.assign({}, base, CMP_PROD_OVR[row.k] || {});
  // 정가(data.js) 위에 서버 발행 할인정책 적용 — 간단 가격표와 동일 엔진/정책
  const pr = (window.CightPricing && row.p)
    ? window.CightPricing.apply(row.p, { tier, step, key: row.k })
    : row.p;
  const tr = prodTr(lang, row.k);
  const krDisp = tr && tr.kr ? tr.kr : p.kr;
  const featSrc = tr && tr.feat ? tr.feat : (p.feat || []);
  const feats = featSrc.slice(0,2).join(' · ');
  const recTxt = (tr && tr.rec) ? tr.rec : (p.rec || '');
  const L = L_(lang);
  const isInd = row.k === 'smartlife_ind';
  const lvl = isInd ? 3 : 2;
  const tierT = isInd ? L.mtrInd : L.mtrLife;
  const art = (window.LENS_ART && window.DESIGN_ART) ? (window.LENS_ART[window.DESIGN_ART[row.k]] || '') : '';
  return (
    <div className={"cmp-card"+(up?" up":"")+(rec?" rec":"")}>
      {rec && <span className="cmp-recbadge">{L.recTag} · {rec}</span>}
      <div className="cmp-cbody">
      <div className="cmp-chead">
        <span className="cmp-shot" dangerouslySetInnerHTML={{__html: art}}></span>
        <div className="cmp-cname2">
          <b>{p.name}{row.star && <sup>*</sup>}</b>
          <em>{krDisp}</em>
        </div>
      </div>
      {feats && <div className="cmp-feat">{feats}</div>}
      {recTxt && (
        <div className="cmp-recfit">
          <span className="cmp-recfit-lab">{L.recFit}</span>
          <span className="cmp-recfit-tx">{recTxt}</span>
        </div>
      )}
      {(()=>{ const st=(window.LENS_STAT||{})[row.k]; if(!st) return null;
        const meter=(v)=>Array.from({length:5},(_,i)=>{
          const cls = (i+1<=v) ? "on" : (i+0.5<=v ? "half" : "");
          return <i key={i} className={cls} />;
        });
        const meterOpt=(v,opt)=>Array.from({length:5},(_,i)=>{
          const cls = i<v ? "on" : (opt && i<opt ? "opt" : "");
          return <i key={i} className={cls} />;
        });
        const sl=L.statLabs||[], el=L.envLabs||[];
        const eo=st.envOpt||[];
        return (
          <div className="cmp-skill">
            <div className="cmp-skill-grp bars">
              <span className="cmp-skill-h">{L.statHead}</span>
              {st.bars.map((v,i)=>(
                <div className="cmp-srow" key={"b"+i}>
                  <span className="cmp-slab">{sl[i]}</span>
                  <span className="cmp-sbar">{meter(v)}</span>
                </div>
              ))}
            </div>
            <div className="cmp-skill-grp env">
              <span className="cmp-skill-h">{L.envHead}</span>
              {st.env.map((v,i)=>{
                const opt = eo[i] && eo[i]>v ? eo[i] : null;
                return (
                  <div className="cmp-srow" key={"e"+i}>
                    <span className="cmp-slab">{el[i]}{opt ? <em className="cmp-opt">+PUV</em> : null}</span>
                    <span className="cmp-sbar env">{opt ? meterOpt(v,opt) : meter(v)}</span>
                  </div>
                );
              })}
            </div>
          </div>
        );
      })()}
      <div className="cmp-prices">
        {[2,1,0].map((i)=>{
          const v = pr[i]; const none = v==null; const free = v===0;
          const isRecIdx = rec && recIdx && CMP_IDX[i].v===recIdx && !none;
          return (
            <div className={"cmp-pcell"+(none?" off":"")+(isRecIdx?" recidx":"")} key={i}>
              <span className="cmp-pidx">{CMP_IDX[i].v}</span>
              <span className={"cmp-pval"+(free?" free":"")}>
                {none ? "–" : free ? "무상" : cwon(v)}
              </span>
            </div>
          );
        })}
      </div>
      </div>
    </div>
  );
}

function rowsForStep(tier, step){
  const table = CMP_T[tier] || [];
  const out = [];
  table.forEach(g=>{
    g.rows.forEach(r=>{
      const eff = CMP_RECLASS[r.k] || g.step;
      if (eff === step) out.push(r);
    });
  });
  return out;
}

function DirCompare({ rx, onChange, onHome, onFov, lang, setLang }){
  const [tier, setTier] = React.useState("LENS");
  const L = L_(lang);
  const total = CMP_COLS.reduce((n,c)=> n + rowsForStep(tier, c.step).length, 0);

  const tierKeys = React.useMemo(()=>{
    const s = new Set();
    (CMP_T[tier]||[]).forEach(g=> g.rows.forEach(r=> s.add(r.k)));
    return s;
  }, [tier]);
  const rec = (rx && typeof window.CIGHT_recommend === 'function')
    ? window.CIGHT_recommend(rx, tierKeys) : null;
  const recBy = rec ? rec.picks : {};
  const recIdx = rec ? rec.idx : null;
  const titleName = (rx && rx.name) || CMP_NAME || '';
  const RE = (window.CIGHT_REASON && window.CIGHT_REASON[lang]) || {};
  const reasonStr = rec ? (rec.reasons||[]).map(c=>RE[c]).filter(Boolean).join(' · ') + ' · ' + tpl(L.idxRec,{idx:rec.idx}) : '';
  const ND = (window.CIGHT_NEED && window.CIGHT_NEED[lang]) || {};
  const AD = (window.CIGHT_ADDON && window.CIGHT_ADDON[lang]) || {};
  const rxLine = rx ? [
    rx.od && (L.od+window.CIGHT_fmtEye(rx.od)),
    rx.os && (L.os+window.CIGHT_fmtEye(rx.os)),
    (rx.age!=null) && (rx.age+L.ageU),
    (rx.digital!=null) && tpl(L.digU,{h:rx.digital})
  ].filter(Boolean).join('  ·  ') : '';

  return (
    <div className="cmp-app">
      <div className="cmp-top">
        <div className="cmp-brand">
          <img className="cmp-logo" src={(window.__resources && window.__resources.logo_teal) || "assets/cight_logo_teal.png"} alt="Cight" role="button" tabIndex={0} title="처음으로" style={{cursor:'pointer'}} onClick={onHome} onKeyDown={(e)=>{ if(e.key==='Enter'||e.key===' '){ e.preventDefault(); onHome&&onHome(); } }} />
          <div>
            <div className="cmp-kicker">{L.kicker}</div>
            <div className="cmp-title">{titleName ? (<React.Fragment><span className="cmp-name">{tpl(L.titleFor,{n:titleName})}</span>{L.titlePlain}</React.Fragment>) : L.titlePlain}</div>
          </div>
        </div>
        <div className="cmp-top-r">
          <CMP_LangSwitch lang={lang} setLang={setLang} />
          {onFov && <button className="cmp-fovbtn" onClick={onFov} title={L.fovBtn}><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z"/><circle cx="12" cy="12" r="3"/></svg><span>{L.fovBtn}</span></button>}
          {onChange && <button className="cmp-change" onClick={onChange}>{L.change}</button>}
          <div className="cmp-tiers">
            {CMP_TIERS.map(t=>{
              const tt = (window.CIGHT_TABS[lang]||window.CIGHT_TABS.ko)[t.id] || {label:t.id,desc:''};
              return (
              <button key={t.id} className={"cmp-tier"+(tier===t.id?" on":"")} onClick={()=>setTier(t.id)}>
                {tt.label}<span>{tt.desc}</span>
              </button>
              );
            })}
          </div>
        </div>
      </div>

      {rec ? (
        <div className="cmp-recbar" title={reasonStr}>
          <span className="cmp-rec-tag">{L.recTag}</span>
          <span className="cmp-rec-name">{rx.name ? rx.name+(honor[lang]||'') : L.cust}</span>
          {rxLine && <span className="cmp-rec-rx">{rxLine}</span>}
          <span className="cmp-rec-why">{reasonStr}</span>
          {rec.needs && rec.needs.length>0 && (
            <span className="cmp-rec-needs">{rec.needs.slice(0,3).map((n,i)=>(<span className="cmp-need" key={i}>{ND[n]||n}</span>))}</span>
          )}
          {rec.addons && rec.addons.length>0 && (
            <span className="cmp-rec-adds"><em>{L.recOptions}</em>{rec.addons.map((a,i)=>(<span className="cmp-add" key={i}>+{AD[a]||a}</span>))}</span>
          )}
        </div>
      ) : (
      <div className="cmp-prog">
        <span className="cmp-prog-l on">{L.progUp}</span>
        <span className="cmp-stair" aria-hidden="true">
          <i style={{height:'100%',opacity:1}} />
          <i style={{height:'78%',opacity:.82}} />
          <i style={{height:'58%',opacity:.64}} />
          <i style={{height:'40%',opacity:.46}} />
          <i style={{height:'26%',opacity:.3}} />
        </span>
        <span className="cmp-prog-t"><b>{L.progB}</b>{L.progRest}</span>
        <span className="cmp-prog-l r">{L.progEco}</span>
      </div>
      )}

      <div className="cmp-cols">
        {CMP_COLS.map(c=>{
          const meta = (window.CIGHT_STEP[lang]||window.CIGHT_STEP.ko)[c.step] || {};
          const list = rowsForStep(tier, c.step);
          return (
            <div className={"cmp-col"+(c.cls?" "+c.cls:"")} key={c.step} data-step={c.step}>
              <div className="cmp-chd">
                <span className="cmp-steplvl" aria-hidden="true">
                  {[1,2,3,4,5].map(n=>(<i key={n} className={n<=c.step?"on":""} />))}
                </span>
                <span className="cmp-rungrow">
                  <span className="cmp-rung"><b>{c.step}</b><span className="cmp-rung-of">/5</span></span>
                  {c.ribbon
                    ? <span className="cmp-ribbon">{L.ribbon}</span>
                    : (c.cat && <span className="cmp-cat">{(window.CIGHT_CAT[lang]||window.CIGHT_CAT.ko)[c.cat]}</span>)}
                </span>
                <span className="cmp-cname">{meta.name}</span>
                <span className="cmp-cdesc">{meta.note}</span>
              </div>
              <div className="cmp-list">
                {list.length===0
                  ? <div className="cmp-card empty"><span>{il('emptyCol',lang)}</span></div>
                  : list.map((r,i)=>{
                      const up = CMP_UPGRADE[r.k];
                      const items = [<CMP_Card key={r.k+i} row={r} cls={c.cls} up={up} rec={recBy[r.k]} recIdx={recIdx} lang={lang} step={c.step} tier={tier} />];
                      if (up && list[i+1]) items.push(
                        <div className="cmp-uplink" key={"ul"+i} aria-hidden="true">
                          <span className="cmp-uparrow">▲</span>
                          <span className="cmp-uptxt">{il('upgrade',lang)}</span>
                        </div>
                      );
                      return items;
                    })}
              </div>
            </div>
          );
        })}
      </div>

      <div className="cmp-foot">
        <span className="cmp-foot-l">{tpl(L.footTotal,{n:total})} · <span className="cmp-fn">{L.footNote}</span></span>
        <span className="cmp-legend">
          <span className="cmp-leg"><i className="prem" />{L.legend}</span>
          <span className="cmp-foot-r">{L.footAddon}</span>
        </span>
      </div>
    </div>
  );
}

/* ===== 고객 선택 첫 화면 ===== */
const CMP_NEEDLAB = { night_drive:'야간운전', digital:'디지털', near:'근거리', sports:'스포츠', indoor:'실내',
  outdoor:'야외', glare:'눈부심', halo:'빛번짐', night:'야간시야', fatigue:'눈피로', dizzy:'적응', headache:'두통', uv:'자외선' };

function CMP_SelCard({ c, onPick, lang }){
  const L = L_(lang); const ND = (window.CIGHT_NEED && window.CIGHT_NEED[lang]) || {};
  const line = [ c.od && (L.od+window.CIGHT_fmtEye(c.od)), c.os && (L.os+window.CIGHT_fmtEye(c.os)) ].filter(Boolean).join('   ·   ');
  const sub = [ (c.age!=null)&&(c.age+L.ageU), (c.digital!=null)&&tpl(L.digU,{h:c.digital}) ].filter(Boolean).join(' · ');
  const rec = (typeof window.CIGHT_recommend === 'function') ? window.CIGHT_recommend(c, new Set(Object.keys(CMP_P))) : null;
  const tags = rec ? (rec.needs||[]) : [];
  return (
    <button className="sel-card" onClick={()=>onPick(c)}>
      <div className="sel-card-top"><b>{c.name||L.cust}</b>{sub && <em>{sub}</em>}</div>
      {line && <div className="sel-card-rx">{line}</div>}
      {tags.length>0 && <div className="sel-card-tags">{tags.map((t,i)=>(<span key={i} className="sel-tag">{ND[t]||t}</span>))}</div>}
      <span className="sel-card-go">{L.selGo}</span>
    </button>
  );
}

function CMP_Manual({ onPick, onClose, lang }){
  const L = L_(lang); const ND = (window.CIGHT_NEED && window.CIGHT_NEED[lang]) || {};
  const [f, setF] = React.useState({ name:'', age:'', digital:'', sphR:'', cylR:'', sphL:'', cylL:'' });
  const set = (k)=> (e)=> setF(p=> Object.assign({}, p, { [k]: e.target.value }));
  const [tags, setTags] = React.useState({});
  const toggle = (k)=> ()=> setTags(p=> Object.assign({}, p, { [k]: !p[k] }));
  const HABIT = ['night_drive','digital','near','outdoor'];
  const DISC = ['glare','halo','night','fatigue','dizzy','uv'];
  const submit = ()=>{
    const habits=[], disc=[];
    Object.keys(tags).forEach(k=>{ if(tags[k]){ (HABIT.indexOf(k)>=0?habits:disc).push(k); } });
    const raw = { name:f.name, age:f.age, digital:f.digital,
      sphR:f.sphR, cylR:f.cylR, sphL:(f.sphL||f.sphR), cylL:(f.cylL||f.cylR),
      habits:habits, discomfort:disc };
    const r = (window.CIGHT_normRx || ((x)=>x))(raw) || raw;
    onPick(r);
  };
  return (
    <div className="man-wrap" onClick={onClose}>
      <div className="man" onClick={e=>e.stopPropagation()}>
        <div className="man-h"><b>{L.manTitle}</b><button className="man-x" onClick={onClose}>✕</button></div>
        <div className="man-row"><label>{L.manName}</label><input value={f.name} onChange={set('name')} /></div>
        <div className="man-row3">
          <span><label>{L.manAge}</label><input value={f.age} onChange={set('age')} placeholder="43" /></span>
          <span><label>{L.manDigital}</label><input value={f.digital} onChange={set('digital')} placeholder="7" /></span>
        </div>
        <div className="man-eye">
          <div className="man-eye-lab">{L.manOD}</div>
          <span><label>S</label><input value={f.sphR} onChange={set('sphR')} placeholder="-5.25" /></span>
          <span><label>C</label><input value={f.cylR} onChange={set('cylR')} placeholder="-1.50" /></span>
        </div>
        <div className="man-eye">
          <div className="man-eye-lab">{L.manOS}</div>
          <span><label>S</label><input value={f.sphL} onChange={set('sphL')} placeholder={L.manSame} /></span>
          <span><label>C</label><input value={f.cylL} onChange={set('cylL')} placeholder={L.manSame} /></span>
        </div>
        <div className="man-tags">
          <div className="man-tags-lab">{L.manHabits}</div>
          {HABIT.map(k=>(<button key={k} className={"man-tag"+(tags[k]?" on":"")} onClick={toggle(k)}>{ND[k]||k}</button>))}
        </div>
        <div className="man-tags">
          <div className="man-tags-lab">{L.manDisc}</div>
          {DISC.map(k=>(<button key={k} className={"man-tag"+(tags[k]?" on":"")} onClick={toggle(k)}>{ND[k]||k}</button>))}
        </div>
        <button className="man-submit" onClick={submit}>{L.manSubmit}</button>
      </div>
    </div>
  );
}

function CMP_Selector({ customers, onPick, onBrowse, onHome, lang, setLang }){
  const L = L_(lang);
  const [q, setQ] = React.useState('');
  const [manual, setManual] = React.useState(false);
  const list = customers.filter(c=> !q || (c.name && c.name.indexOf(q)>=0));
  return (
    <div className="sel">
      <div className="sel-head">
        <img className="sel-logo" src={(window.__resources && window.__resources.logo_teal) || "assets/cight_logo_teal.png"} alt="Cight" role="button" tabIndex={0} title="처음으로" style={{cursor:'pointer'}} onClick={onHome} onKeyDown={(e)=>{ if(e.key==='Enter'||e.key===' '){ e.preventDefault(); onHome&&onHome(); } }} />
        <div className="sel-head-t">
          <div className="sel-kicker">{L.selKicker}</div>
          <h1 className="sel-title">{L.selTitle}</h1>
        </div>
        <CMP_LangSwitch lang={lang} setLang={setLang} />
      </div>
      <div className="sel-bar">
        <input className="sel-input" placeholder={L.selSearch} value={q} onChange={e=>setQ(e.target.value)} />
        <button className="sel-btn" onClick={()=>setManual(true)}>{L.selManual}</button>
        <button className="sel-btn ghost" onClick={onBrowse}>{L.selBrowse}</button>
      </div>
      <div className="sel-grid">
        {list.length ? list.map(c=>(<CMP_SelCard key={c.id} c={c} onPick={onPick} lang={lang} />))
          : <div className="sel-empty">{customers.length ? L.selEmptyHas : L.selEmptyNone}</div>}
      </div>
      {manual && <CMP_Manual onPick={onPick} onClose={()=>setManual(false)} lang={lang} />}
    </div>
  );
}

function S2Grid({ level }){
  // 설계 등급별 왜곡 계수(배럴) — STEP1(구면) 큼, STEP5(개인맞춤) 거의 0
  const AMP = { 1:0.16, 2:0.105, 3:0.06, 4:0.026, 5:0.006 };
  const amp = AMP[level] != null ? AMP[level] : 0.08;
  const ref = React.useRef(null);
  const lensRef = React.useRef(null);
  const VB = 100, half = VB/2;
  const SCALE = 30;            // 단위 → viewBox
  const R2MAX = 2.0;           // 왜곡 폭주 방지(가장자리 클램프)
  const SAMP = 12;
  React.useEffect(()=>{
    const svg = ref.current; if(!svg) return;
    const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const us = [-1.5,-1,-0.5,0,0.5,1,1.5];
    const vs = [-1.5,-1,-0.5,0,0.5,1,1.5];
    const vpaths = us.map(()=>{ const p=document.createElementNS('http://www.w3.org/2000/svg','path'); p.setAttribute('class','s2g-line'); svg.appendChild(p); return p; });
    const hpaths = vs.map(()=>{ const p=document.createElementNS('http://www.w3.org/2000/svg','path'); p.setAttribute('class','s2g-line'); svg.appendChild(p); return p; });
    // 렌즈 중심 cx 기준 배럴 왜곡(초점=화면 중앙 고정, 렌즈만 좌우 이동)
    function warp(u,v,cx,k){ const du=u-cx; let r2=du*du+v*v; if(r2>R2MAX) r2=R2MAX; const f=1+k*r2; return [half+(cx+du*f)*SCALE, half+v*f*SCALE]; }
    function build(cx,k){
      for(let i=0;i<us.length;i++){ const u0=us[i]; let d='';
        for(let j=0;j<=SAMP;j++){ const v=-1.5+(3*j/SAMP); const [x,y]=warp(u0,v,cx,k); d+=(j?'L':'M')+x.toFixed(2)+' '+y.toFixed(2)+' '; }
        vpaths[i].setAttribute('d',d);
      }
      for(let i=0;i<vs.length;i++){ const v0=vs[i]; let d='';
        for(let j=0;j<=SAMP;j++){ const u=-1.5+(3*j/SAMP); const [x,y]=warp(u,v0,cx,k); d+=(j?'L':'M')+x.toFixed(2)+' '+y.toFixed(2)+' '; }
        hpaths[i].setAttribute('d',d);
      }
    }
    function moveLens(cx){ if(lensRef.current) lensRef.current.style.left = (50 + cx*SCALE) + '%'; }
    if(reduce){ build(0.42,amp); moveLens(0.42); return; }
    build(0,amp); moveLens(0);
    let raf, start=null;
    const speed = window.S2_GAZE_SPEED || 0.00094;   // 렌즈 좌우 1주기 ≈ 6.7s
    function tick(ts){
      if(start==null) start=ts;
      const cx = Math.sin((ts-start)*speed)*0.5;     // 렌즈 중심 좌우 이동(중앙에서 시작)
      build(cx, amp);
      moveLens(cx);
      raf=requestAnimationFrame(tick);
    }
    raf=requestAnimationFrame(tick);
    function onVis(){ if(document.visibilityState==='visible'){ cancelAnimationFrame(raf); start=null; raf=requestAnimationFrame(tick); } }
    document.addEventListener('visibilitychange', onVis);
    return ()=>{ cancelAnimationFrame(raf); document.removeEventListener('visibilitychange', onVis); while(svg.firstChild) svg.removeChild(svg.firstChild); };
  }, [level, amp]);
  return (
    <span className={"s2grid lv"+level}>
      <svg ref={ref} className="s2grid-svg" viewBox={"0 0 "+VB+" "+VB} preserveAspectRatio="none" aria-hidden="true"></svg>
      <span ref={lensRef} className="s2lens" aria-hidden="true" />
      <span className="s2focus" aria-hidden="true" />
    </span>
  );
}

function S2Eye({ level }){
  // 눈은 고정 · 안경렌즈(원형)가 위를 지나며 그 안의 눈만 작아 보임 (마이너스 렌즈 축소)
  const src = (window.__resources && window.__resources.eye_natural) || "assets/eye_natural.png";
  return (
    <span className={"s2eye s2eye-lv"+level}>
      <img className="s2eye-base" src={src} alt="" />
      <span className="s2eye-lens" aria-hidden="true">
        <img className="s2eye-inner" src={src} alt="" />
      </span>
    </span>
  );
}

function CMP_Guide({ lang, setLang, onStart }){
  const G = (window.CIGHT_GUIDE && window.CIGHT_GUIDE[lang]) || window.CIGHT_GUIDE.ko;
  const ST = (window.CIGHT_STEP[lang] || window.CIGHT_STEP.ko);
  const S2 = (window.CIGHT_S2 && window.CIGHT_S2[lang]) || (window.CIGHT_S2 && window.CIGHT_S2.ko) || {d:{},e:{}};
  const TH = (window.CIGHT_THK && window.CIGHT_THK[lang]) || (window.CIGHT_THK && window.CIGHT_THK.ko) || {};
  const CG = (window.CIGHT_CG && window.CIGHT_CG[lang]) || (window.CIGHT_CG && window.CIGHT_CG.ko) || {};
  const THIDX = window.CIGHT_THK_IDX || ['1.60','1.67','1.74'];
  const CGIC = window.CIGHT_CG_ICONS || [];
  const CGTGT = window.CIGHT_CG_TGTIC || '';
  const art = (k)=> ({__html: (window.LENS_ART && window.LENS_ART[k]) || ''});
  const mats = [['1.60','men160'],['1.67','men167'],['1.74','men174']];
  const s2steps = [1,2,3,4,5];
  const coats = [['c_puv',G.c1],['c_glare',G.c2],['c_color',G.c3]];

  const pages = [
    (
      <div className="gp gp-hero-pg" key="hero">
        <div className="gp-hero">
          <div className="gp-hero-tx">
            <div className="gd-kicker">{G.kicker}</div>
            <h1 className="gd-title">{G.title}</h1>
            <p className="gd-sub">{G.sub}</p>
          </div>
          <span className="gp-hero-img"><image-slot id="gd-hero" shape="rounded" radius="20" fit="cover" placeholder={G.heroPhoto} style={{display:'block',width:'100%',height:'100%'}}></image-slot></span>
        </div>
        <div className="gd-pillars">
          {[['01',G.p1t,G.p1d],['02',G.p2t,G.p2d],['03',G.p3t,G.p3d]].map((p,i)=>(
            <div className="gd-pill" key={i}><span className="gd-pill-n">{p[0]}</span><b>{p[1]}</b><span className="gd-pill-d">{p[2]}</span></div>
          ))}
        </div>
      </div>
    ),
    (
      <div className="gp gp-thk" key="s1">
        <div className="gp-head">
          <span className="gd-sec-tag">{G.s1tag}</span>
          <h2>{TH.title[0]}<span className="acc">{TH.title[1]}</span>{TH.title[2]}</h2>
          <p>{TH.sub[0]}<b>{TH.sub[1]}</b>{TH.sub[2]}</p>
        </div>
        <div className="thkg">
          {[0,1,2].map(i=>(
            <div className={"thkc"+(i===2?" hl":"")} key={i}>
              <div className="thkc-head">
                <span className="thkc-badge">{THIDX[i]}</span>
                <span className="thkc-name">{TH.names[i][0]}{TH.names[i][1] && <em>{TH.names[i][1]}</em>}</span>
              </div>
              <div className="thkc-side">
                <p className="thkc-sidetx">{TH.side[i][0]}<b>{TH.side[i][1]}</b>{TH.side[i][2]}</p>
                <span className="thkc-pic"><img src={(window.__resources&&window.__resources["thk_side_"+i])||("assets/ref/side_"+i+".png")} alt="" /></span>
              </div>
              <div className="thkc-coin">
                <span className="thkc-coin-main">{TH.coin[i][0]}<b>{TH.coin[i][1]}</b>{TH.coin[i][2]}</span>
                <span className="thkc-coin-sub">{TH.coin[i][3]}</span>
                <div className="thkc-cmp">
                  <img className="thkc-lens" src={(window.__resources&&window.__resources["thk_lensd_"+i])||("assets/ref/lensd_"+i+".png")} alt="" />
                  <span className="thkc-eq">≈</span>
                  <img className="thkc-coins" src={(window.__resources&&window.__resources["thk_coins_"+i])||("assets/ref/coins_"+i+".png")} alt="" />
                </div>
              </div>
            </div>
          ))}
        </div>
        <p className="idxnote">{TH.note}</p>
      </div>
    ),
    (
      <div className="gp gp-s2" key="s2">
        <div className="gp-head"><span className="gd-sec-tag">{G.s2tag}</span><h2>{G.s2t}</h2><p>{G.s2d}</p></div>
        <div className="s2matrix">
          <div className="s2rowlab s2corner" />
          {s2steps.map(s=>(
            <div className={"s2colhead"+(s===5?" hl":"")} key={"h"+s}>
              <span className="s2step">{"STEP "+s}</span>
              <b>{ST[s].name}</b>
            </div>
          ))}
          <div className="s2rowlab"><span className="s2rl-ic">▦</span>{S2.rowD}</div>
          {s2steps.map(s=>(
            <div className={"s2cell"+(s===5?" hl":"")} key={"d"+s}>
              <S2Grid level={s} />
              <span className="s2t">{S2.d[s] && S2.d[s][0]}</span>
              <span className="s2d">{S2.d[s] && S2.d[s][1]}</span>
            </div>
          ))}
          <div className="s2rowlab"><span className="s2rl-ic">◉</span>{S2.rowE}</div>
          {s2steps.map(s=>(
            <div className={"s2cell"+(s===5?" hl":"")} key={"e"+s}>
              <S2Eye level={s} />
              <span className="s2t">{S2.e[s] && S2.e[s][0]}</span>
              <span className="s2d">{S2.e[s] && S2.e[s][1]}</span>
            </div>
          ))}
        </div>
        <p className="s2foot">{S2.foot}</p>
      </div>
    ),
    (
      <div className="gp gp-cg" key="s3">
        <div className="gp-head">
          <span className="gd-sec-tag">{G.s3tag}</span>
          <h2>{CG.title[0]}<span className="acc">{CG.title[1]}</span>{CG.title[2]}</h2>
          <p>{CG.sub[0]}<b>{CG.sub[1]}</b>{CG.sub[2]}</p>
        </div>
        <div className="cg-wrap">
          {[0,1].map(g=>(
            <div className="cg-group" key={g}>
              <div className="cg-grouplbl">{CG.groups[g]}</div>
              <div className="cgg">
                {[0,1,2].map(j=>{ const idx=g*3+j; const c=CG.coats[idx]||{}; return (
                  <div className="cgc" key={idx}>
                    <div className="cgc-top">
                      <span className="cgc-icon" dangerouslySetInnerHTML={{__html:CGIC[idx]||''}}></span>
                      <div className="cgc-head"><span className="cgc-name">{c.n}</span><span className="cgc-brand">{c.b}</span></div>
                    </div>
                    <p className="cgc-eff">{c.e}</p>
                    <span className="cgc-tgt"><span className="cgc-tgt-ic" dangerouslySetInnerHTML={{__html:CGTGT}}></span><span>{c.t}</span></span>
                  </div>
                );})}
              </div>
            </div>
          ))}
        </div>
      </div>
    ),
    // 마무리(CTA) 페이지는 고객선택 다음 단계(CMP_EndPage)로 이동 — 2026-06-10 ⑤⑥ 순서 교체
  ];

  const [page, setPage] = React.useState(0);
  const last = pages.length - 1;
  const go = (n)=> setPage(Math.max(0, Math.min(last, n)));
  React.useEffect(()=>{
    const onKey = (e)=>{ if(e.key==='ArrowRight') go(page+1); else if(e.key==='ArrowLeft') go(page-1); };
    window.addEventListener('keydown', onKey);
    return ()=> window.removeEventListener('keydown', onKey);
  }, [page]);

  return (
    <div className="gd paged">
      <div className="gd-top">
        <img className="gd-logo" src={(window.__resources&&window.__resources.logo_teal)||"assets/cight_logo_teal.png"} alt="Cight" role="button" tabIndex={0} title="처음으로" style={{cursor:'pointer'}} onClick={()=>go(0)} onKeyDown={(e)=>{ if(e.key==='Enter'||e.key===' '){ e.preventDefault(); go(0); } }} />
        <span className="gd-top-sp" />
        <CMP_LangSwitch lang={lang} setLang={setLang} />
        <button className="gd-cta" onClick={onStart}>{G.cta}</button>
      </div>
      <div className="gd-viewport">
        <div className="gd-track" style={{width:(pages.length*100)+'%',transform:`translateX(-${page*(100/pages.length)}%)`}}>
          {pages.map((pg,i)=>(<div className="gd-slot" key={i} style={{width:(100/pages.length)+'%'}} aria-hidden={i!==page}>{pg}</div>))}
        </div>
      </div>
      <div className="gd-nav">
        <button className="gd-arrow" onClick={()=>go(page-1)} disabled={page===0} aria-label={G.prev}>‹</button>
        <div className="gd-dots">
          {pages.map((_,i)=>(<button key={i} className={"gd-dot"+(i===page?" on":"")} onClick={()=>go(i)} aria-label={"page "+(i+1)} />))}
        </div>
        {page===last
          ? <button className="gd-arrow next cta" onClick={onStart}>{G.cta}</button>
          : <button className="gd-arrow next" onClick={()=>go(page+1)} aria-label={G.next}>›</button>}
      </div>
    </div>
  );
}

/* 마무리(CTA) 페이지 — 가이드 ⑤번째였던 슬라이드를 고객선택 '다음' 단계로 분리 (⑤⑥ 교체) */
function CMP_EndPage({ lang, setLang, onGo, onHome }){
  const G = (window.CIGHT_GUIDE && window.CIGHT_GUIDE[lang]) || window.CIGHT_GUIDE.ko;
  return (
    <div className="gd paged">
      <div className="gd-top">
        <img className="gd-logo" src={(window.__resources&&window.__resources.logo_teal)||"assets/cight_logo_teal.png"} alt="Cight" role="button" tabIndex={0} title="처음으로" style={{cursor:'pointer'}} onClick={onHome} onKeyDown={(e)=>{ if(e.key==='Enter'||e.key===' '){ e.preventDefault(); onHome&&onHome(); } }} />
        <span className="gd-top-sp" />
        <CMP_LangSwitch lang={lang} setLang={setLang} />
        <button className="gd-cta" onClick={onGo}>{G.cta}</button>
      </div>
      <div className="gd-viewport">
        <div className="gd-track" style={{width:'100%'}}>
          <div className="gd-slot" style={{width:'100%'}}>
            <div className="gp gp-end-pg">
              <div className="gp-end">
                <h2 className="gp-end-t">{G.endT}</h2>
                <button className="gd-cta big" onClick={onGo}>{G.cta}</button>
                <span className="gd-foot">{G.foot}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function CMP_App(){
  const [rx, setRx] = React.useState(CMP_RX);
  const [mode, setMode] = React.useState(CMP_RX ? 'table' : 'guide');
  const [customers, setCustomers] = React.useState(CMP_CUSTOMERS);
  const [lang, setLangS] = React.useState(CMP_LANG0);
  const setLang = (l)=>{ setLangS(l); try{ localStorage.setItem('cight_lang', l); }catch(e){} };

  // 서버 발행 할인정책이 갱신되면(fetch/발행) 가격 다시 그림
  const [, bumpPolicy] = React.useState(0);
  React.useEffect(()=>{
    const h = ()=> bumpPolicy(x=>x+1);
    window.addEventListener('cight-pricing-change', h);
    return ()=> window.removeEventListener('cight-pricing-change', h);
  }, []);

  React.useEffect(()=>{
    const norm = window.CIGHT_normRx || ((x)=>x);
    let alive = true;

    // 허용 출처: 같은 origin 또는 *.cight.co.kr (임베드 부모)
    function okOrigin(origin){
      if(origin === window.location.origin) return true;
      try{ return /(^|\.)cight\.co\.kr$/.test(new URL(origin).hostname); }catch(e){ return false; }
    }
    function onMsg(e){
      if(!okOrigin(e.origin)) return;            // 보안: 신뢰 출처만 수용
      const d = e.data || {};
      if(d.type === 'CIGHT_CUSTOMER' && d.payload){
        const n = norm(d.payload); if(n){ setRx(n); setMode('table'); }
      } else if(d.type === 'CIGHT_CUSTOMERS' && Array.isArray(d.payload)){
        const list = d.payload.map((c,i)=>{ const r = norm(c)||{}; r.id = (c&&c.id!=null)?c.id:('c'+i); return r; }).filter(r=> r && (r.name||r.od||r.os));
        setCustomers(list); setMode('select');
      }
    }
    window.addEventListener('message', onMsg);
    // 부모(os)에 준비완료 알림 → 부모가 이때 데이터 전송 (URL 노출 0)
    try{ if(window.parent && window.parent !== window) window.parent.postMessage({ type:'CIGHT_READY' }, '*'); }catch(e){}

    // 같은 도메인(os 하위 배포) 세션 기반 자동 fetch — id만 사용, PII는 URL에 없음
    try{
      const cid = new URLSearchParams(location.search).get('customerId') || window.CIGHT_CUSTOMER_ID;
      if(cid && !CMP_RX){
        const base = window.CIGHT_API_BASE || '/api/customers/';
        fetch(base + encodeURIComponent(cid), { credentials:'include', headers:{ 'Accept':'application/json' } })
          .then(r=> r.ok ? r.json() : null)
          .then(j=>{ if(alive && j){ const n = norm(j); if(n){ setRx(n); setMode('table'); } } })
          .catch(()=>{});
      }
    }catch(e){}

    return ()=>{ alive = false; window.removeEventListener('message', onMsg); };
  }, []);

  if(mode==='guide') return <CMP_Guide lang={lang} setLang={setLang} onStart={()=>{ setRx(null); setMode('select'); }} />;
  if(mode==='select') return <CMP_Selector customers={customers} onPick={(c)=>{ setRx(c); setMode('end'); }} onBrowse={()=>{ setRx(null); setMode('end'); }} onHome={()=>setMode('guide')} lang={lang} setLang={setLang} />;
  if(mode==='end') return <CMP_EndPage lang={lang} setLang={setLang} onGo={()=>setMode('table')} onHome={()=>setMode('guide')} />;
  if(mode==='fov' && window.CMP_FOV) return <window.CMP_FOV rx={rx} lang={lang} setLang={setLang} onHome={()=>setMode('guide')} onBack={()=>setMode('table')} LangSwitch={CMP_LangSwitch} />;
  return <DirCompare rx={rx} onChange={()=>setMode('select')} onHome={()=>setMode('guide')} onFov={()=>setMode('fov')} lang={lang} setLang={setLang} />;
}

ReactDOM.createRoot(document.getElementById('root')).render(<CMP_App />);
