/* normal-mode.jsx — 노멀 모드 (이지의 정답형 명료함 + 스탠다드의 시각적 설득을 결합)
   "한 화면 결정 브리핑": 결정 히어로 → 비중 추천 → 페르소나 미니 3종 → KPI·키워드 → 첫 액션.
   무중단 가산: 기존 이지/스탠다드/익스텐션 일절 변경 없음. 같은 엔진(runBrandPipeline)을 재사용.
   원칙(CLAUDE.md): 측정=tier A, 표본=tier C(거짓정밀 금지). 비중은 고정정답 아님 → 퍼널·신뢰구간 동반(DP-5).
*/
const { useState: useNMState } = React;

function NormalMode({ onGotoStandard }) {
  const [step, setStep] = useNMState('input');
  const [brand, setBrand] = useNMState('');
  const [result, setResult] = useNMState(null);
  const [pct, setPct] = useNMState(0);
  const [copied, setCopied] = useNMState(null);

  async function run() {
    if (!brand.trim()) return;
    setStep('loading');
    for (const p of [15, 35, 60, 85, 100]) {
      setPct(p);
      await new Promise(r => setTimeout(r, 360 + Math.random() * 260));
    }
    setResult(await computeNormal(brand.trim()));
    setStep('result');
  }

  // 공개(다수 사용자) 표면: 적재 1st-party는 노출하지 않는다.
  //  업종 해석은 공개 카탈로그(shopSearch, tier-B 추정)로만. 적재 브랜드라도 식별정보 노출 없이
  //  표본 prior(tier-C)로만 처리(아래 suppressMeasured). 거짓정밀 금지: 무결과면 빈 채로 둔다.
  async function resolveCategory(name) {
    try {
      if (window.DataLab && window.DataLab.shopSearch) {
        const sr = await window.DataLab.shopSearch({ query: name, display: 20 });
        const items = (sr && sr.items) || [];
        if (items.length) {
          const own = items.find(it => it.brand === name || (it.mallName || '').includes(name)) || items[0];
          const category = [own.category1, own.category2, own.category3].filter(Boolean).join(' > ');
          // keywords는 비워둠 — 브랜드명/식별어가 결과에 새지 않게.
          if (category) return { category, keywords: '', tier: 'B', source: sr.__source === 'real' ? 'shopSearch' : 'shopSearch(mock)' };
        }
      }
    } catch (e) {}
    return { category: '', keywords: '', tier: null, source: 'none' };
  }

  async function computeNormal(name) {
    let pipe = null;
    const resolved = await resolveCategory(name);
    try {
      // suppressMeasured: 적재 실측 hard-apply 끔 → 표본 prior(tier-C)로만. 공개 표면에서 브랜드 식별 차단.
      if (window.runBrandPipeline) pipe = window.runBrandPipeline({ name, category: resolved.category, keywords: resolved.keywords, description: '' }, { suppressMeasured: true });
    } catch (e) {}
    const personas = (pipe && pipe.personas) || [];
    const top = personas[0];
    if (!top) return { name, empty: true, resolved };

    const r = top.result || {};
    const leaves = top.query.flatMap(g => g.leaves).slice(0, 5);
    const kwSets = window.KeywordEngine?.generateKeywordSets([{ op: 'OR', leaves }]) || [];
    // 입력한 브랜드명/식별어가 키워드 칩에 새지 않도록 방어 필터(공개 표면).
    const nm = name.trim();
    const keywords = [...new Set(kwSets.flatMap(s => s.keywords || []))]
      .filter(k => k && !(nm && k.includes(nm)))
      .slice(0, 6);

    const ages = window.SimEngine?.AGES || [];
    const ageDist = r.ageDist || [];
    const topAgeIdx = ageDist.length ? ageDist.reduce((mi, v, i, a) => v > a[mi] ? i : mi, 0) : -1;
    const topAge = topAgeIdx >= 0 && ages[topAgeIdx] ? ages[topAgeIdx] : '30대';
    const gF = r.genderDist?.F || 0.5;
    const gender = gF > 0.6 ? '여성 중심' : gF < 0.4 ? '남성 중심' : '남녀 균형';
    const topCats = top.query.flatMap(g => g.leaves).slice(0, 3).map(l => l.split(' > ').pop());

    return {
      name,
      // 파이프 데이터 등급 플래그(tier-polish gradeOf 가 읽음)
      measuredProfile: pipe && pipe.measuredProfile,
      salesProfile: pipe && pipe.salesProfile,
      referenceProfile: pipe && pipe.referenceProfile,
      brandMetaProfile: pipe && pipe.brandMetaProfile,
      personas: personas.slice(0, 3),
      top,
      reach: r.finalReach || 0,
      ctr: r.ctr || 0,
      validity: r.validity || 0,
      topAge, gender, topCats, keywords, resolved,
    };
  }

  function copyText(text, key) {
    window.safeCopy?.(text);
    setCopied(key);
    setTimeout(() => setCopied(null), 1600);
  }

  return (
    <div className="nm-shell">
      <div className="nm-body">
        {step === 'input' && <NMInput brand={brand} setBrand={setBrand} onRun={run} onGotoStandard={onGotoStandard} />}
        {step === 'loading' && <NMLoading pct={pct} />}
        {step === 'result' && result && (
          <NMResult result={result} copied={copied} onCopy={copyText} onGotoStandard={onGotoStandard}
            onReset={() => { setStep('input'); setBrand(''); setResult(null); setPct(0); }} />
        )}
      </div>
      <NMStyles />
    </div>
  );
}

/* ── Input ── */
function NMInput({ brand, setBrand, onRun, onGotoStandard }) {
  const examples = ['프리미엄 골프 용품', '건강기능식품', '여성 패션몰', '캠핑 아웃도어'];
  return (
    <div className="nm-input-wrap">
      <div className="nm-hero-in">
        <div className="nm-badge-in">노멀 모드</div>
        <h1>어떤 브랜드의 광고 전략이 필요하세요?</h1>
        <p>브랜드명 하나로 <b>결정 → 근거 → 액션</b>을 한 화면에 정리해 드립니다.</p>
      </div>
      <div className="nm-input-row">
        <input className="nm-input" placeholder="예: 브랜드명, 제품 카테고리..." value={brand}
          onChange={e => setBrand(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && brand.trim() && onRun()} autoFocus />
        <button className="nm-run-btn" onClick={onRun} disabled={!brand.trim()}>분석 시작 →</button>
      </div>
      <div className="nm-examples">
        {examples.map(ex => <button key={ex} className="nm-ex-chip" onClick={() => setBrand(ex)}>{ex}</button>)}
      </div>
    </div>
  );
}

/* ── Loading ── */
function NMLoading({ pct }) {
  const msg = pct < 35 ? '브랜드 카테고리 파악 중…' : pct < 70 ? '페르소나·비중 매칭 중…' : '결정 브리핑 구성 중…';
  return (
    <div className="nm-loading">
      <div className="nm-load-ring"></div>
      <div className="nm-load-title">분석 중</div>
      <div className="nm-load-bar"><div style={{ width: pct + '%' }} /></div>
      <div className="nm-load-hint">{msg}</div>
    </div>
  );
}

/* ── 페르소나 비중 split (leaf 기반 + tier 보정) ── */
function splitOf(p) {
  const leaves = p.query.flatMap(g => g.leaves);
  const intent = leaves.filter(l => /구매의도|구매 의도/.test(l)).length;
  let buy = Math.round((intent / (leaves.length || 1)) * 100);
  if (p.tier === 'intent') buy = Math.max(buy, 60);
  else if (p.tier === 'interest') buy = Math.min(buy || 40, 45);
  buy = Math.max(20, Math.min(80, buy || 50));
  return { interest: 100 - buy, intent: buy };
}
function bidOf(p) {
  return p.tier === 'intent' ? '입찰 · 의도 정밀'
    : p.tier === 'interest' ? '입찰 · 관심 광역'
    : p.tier === 'mixed' ? '입찰 · 결합 정밀'
    : '입찰 · 신규 탐색';
}

/* ── Result ── */
function NMResult({ result, copied, onCopy, onReset, onGotoStandard }) {
  if (result.empty) {
    return (
      <div className="nm-result">
        <div className="nm-empty">
          <p><strong>{result.name}</strong>과 매칭되는 카테고리를 찾지 못했습니다.</p>
          <p className="nm-empty-hint">스탠다드 모드에서 카테고리를 직접 선택해 보세요.</p>
          <div style={{ display: 'flex', gap: 8, marginTop: 16 }}>
            <button className="nm-reset" onClick={onReset}>↺ 다시 입력</button>
            <button className="nm-up-btn" onClick={onGotoStandard}>스탠다드 모드로 →</button>
          </div>
        </div>
      </div>
    );
  }
  const { name, reach, ctr, validity, topAge, gender, topCats, keywords, personas } = result;
  const SE = window.SimEngine;
  const grade = window.tierGradeOf ? window.tierGradeOf(result) : null;
  const lead = topCats[0] || '핵심 카테고리';
  const fit = { repurchase: result.measuredProfile && result.measuredProfile.repurchase, budgetBand: 'mid' };
  const allKw = keywords.join(', ');
  const topSplit = result.top ? splitOf(result.top) : { interest: 50, intent: 50 };
  const intentDom = topSplit.intent >= topSplit.interest;
  const domLabel = intentDom ? '구매의도' : '관심사';
  const domShare = intentDom ? topSplit.intent : topSplit.interest;
  const bidMode = intentDom ? '정밀' : '광역';

  return (
    <div className="nm-result">
      <div className="nm-head">
        <div>
          <div className="nm-eyebrow">분석 완료 · 결정 브리핑</div>
          <h2 className="nm-title">{name}</h2>
          {result.resolved && result.resolved.tier && result.resolved.category && (
            <div style={{ fontSize: 11, marginTop: 4, color: result.resolved.tier === 'A' ? 'var(--plant)' : 'var(--cyan)' }}>
              업종 자동해석: {result.resolved.category} · {result.resolved.tier === 'A' ? '적재 실측(tier-A)' : '실검색 추정(tier-B)'}
            </div>
          )}
        </div>
        <button className="nm-reset" onClick={onReset}>↺ 다시</button>
      </div>

      {/* 1. 결정 히어로 */}
      <div className="nm-hero">
        <div className="nm-hero-lab">권장 설정 {window.TierBadge && <TierBadge grade={grade} compact />}</div>
        <div className="nm-hero-answer">
          주 세그먼트 <b>{result.top ? result.top.name : name}</b> · 우세 신호 <span className={intentDom ? 'nm-coral' : 'nm-violet'}>{domLabel} ‘{lead}’ {domShare}%</span>
        </div>
        <div className="nm-hero-meta">
          <span className="nm-pill">핵심 연령 <b>{topAge}</b></span>
          <span className="nm-pill">성별 <b>{gender}</b></span>
          {reach ? <span className="nm-pill">예상 도달 <b>{SE?.fmtN(reach) || reach}</b></span> : null}
          {validity ? <span className="nm-pill">정확도 <b>{validity}%</b></span> : null}
        </div>
      </div>

      {/* 2. 비중 추천 */}
      <div className="nm-slab">비중 추천 <span className="h">퍼널을 바꾸면 추천이 따라옵니다</span></div>
      <div className="nm-card">
        {window.FunnelWeighting && <FunnelWeighting fit={fit} />}
      </div>

      {/* 3. 페르소나 미니 3종 */}
      <div className="nm-slab">페르소나 <span className="h">핵심만 — 깊게 보려면 스탠다드</span></div>
      <div className="nm-personas">
        {personas.map((p, i) => {
          const sp = splitOf(p);
          const pg = (result.measuredProfile && p.tier !== 'mobile') ? 'A' : 'C';
          const pl = p.query.flatMap(g => g.leaves)[0]?.split(' > ').pop() || '';
          return (
            <div key={p.id || i} className="nm-pm">
              <div className="nm-pm-pn"><b>{p.name}</b>{window.TierBadge && <TierBadge grade={pg} compact />}</div>
              {pl ? <span className="nm-leaf">{pl}</span> : null}
              <div className="nm-mnum"><span className="iv">관심 {sp.interest}</span><span className="bv">의도 {sp.intent}</span></div>
              <div className="nm-mbar"><div className="i" style={{ width: sp.interest + '%' }}></div><div className="b" style={{ width: sp.intent + '%' }}></div></div>
              <div className="nm-chips">
                <span className="nm-chip bid">{bidOf(p)}</span>
                {p.angle ? <span className="nm-chip angle">소재 · {p.angle}</span> : null}
              </div>
            </div>
          );
        })}
      </div>

      {/* 4. KPI + 키워드 */}
      <div className="nm-slab">실행 지표 · 키워드 <span className="h">바로 복사해서 사용</span></div>
      <div className="nm-kpi">
        <div className="nm-kpibox"><div className="n">{SE?.fmtN(reach) || '—'}</div><div className="l">예상 도달 (명)</div></div>
        <div className="nm-kpibox"><div className="n">{ctr || '—'}%</div><div className="l">예상 CTR</div></div>
        <div className="nm-kpibox"><div className="n sm">{topAge}</div><div className="l">핵심 연령대</div></div>
        <div className="nm-kpibox"><div className="n sm">{gender}</div><div className="l">성별 분포</div></div>
      </div>
      {keywords.length ? (
        <div className="nm-kw">
          <div className="nm-kwhead">
            <span className="t">맞춤타겟 키워드</span>
            <button className="nm-copyall" onClick={() => onCopy(allKw, 'all')}>{copied === 'all' ? '복사됨 ✓' : '전체 복사'}</button>
          </div>
          <div className="nm-kws">
            {keywords.map((k, i) => (
              <button key={k} className={'nm-kwchip' + (i === 0 ? ' seed' : '')} onClick={() => onCopy(k, k)}>
                {k}<span className="i">{copied === k ? '✓' : '📋'}</span>
              </button>
            ))}
          </div>
        </div>
      ) : null}

      {/* 5. 첫 액션 + 업그레이드 */}
      <div className="nm-action">
        <div>
          <div className="nm-stepn">권장 1순위</div>
          <b>{domLabel} ‘{lead}’ 세그먼트 · 예산 비중 {domShare}% · 입찰 {bidMode} 모드 (CVR prior 기준)</b>
        </div>
        <button className="nm-go" onClick={onGotoStandard}>집행 플랜 →</button>
      </div>
      <div className="nm-up">
        <span>더 깊은 분석(퍼널·RFM·입찰 ROAS·집행 계획)이 필요하면</span>
        <button onClick={onGotoStandard}>스탠다드 모드로 →</button>
      </div>
    </div>
  );
}

/* ── Styles (자기완결, nm- 접두 · 기존 토큰 재사용) ── */
function NMStyles() {
  return (
    <style>{`
    .nm-shell{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}
    .nm-body{max-width:880px;margin:0 auto;padding:22px clamp(14px,3vw,28px) 80px}
    /* input */
    .nm-input-wrap{max-width:620px;margin:0 auto;padding-top:8vh}
    .nm-hero-in{text-align:center;margin-bottom:26px}
    .nm-badge-in{display:inline-block;font-family:var(--font-mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--violet-br,oklch(0.80 0.13 300));background:oklch(0.66 0.17 300/.16);border:1px solid oklch(0.72 0.10 300/.24);padding:5px 12px;border-radius:999px;margin-bottom:16px}
    .nm-hero-in h1{font-size:27px;font-weight:800;letter-spacing:-.02em;line-height:1.25}
    .nm-hero-in p{color:var(--text-dim);font-size:14px;margin-top:10px} .nm-hero-in p b{color:var(--text)}
    .nm-input-row{display:flex;gap:9px}
    .nm-input{flex:1;font:inherit;font-size:15px;color:var(--text);background:oklch(0.13 0.018 290/.6);border:1px solid oklch(0.72 0.10 300/.22);border-radius:11px;padding:14px 16px;outline:none}
    .nm-input:focus{border-color:var(--violet-br,oklch(0.80 0.13 300));box-shadow:0 0 0 3px oklch(0.66 0.17 300/.16)}
    .nm-run-btn{white-space:nowrap;font:inherit;font-size:14px;font-weight:700;color:#fff;background:linear-gradient(135deg,oklch(0.66 0.17 300),oklch(0.6 0.17 320));border:none;border-radius:11px;padding:0 20px;cursor:pointer}
    .nm-run-btn:disabled{opacity:.4;cursor:not-allowed}
    .nm-examples{display:flex;gap:7px;flex-wrap:wrap;justify-content:center;margin-top:16px}
    .nm-ex-chip{font:inherit;font-size:12.5px;color:var(--text-dim);background:oklch(0.13 0.018 290/.5);border:1px solid var(--line,oklch(0.72 0.10 300/.13));border-radius:8px;padding:7px 13px;cursor:pointer}
    .nm-ex-chip:hover{color:var(--text);border-color:oklch(0.72 0.10 300/.3)}
    /* loading */
    .nm-loading{max-width:420px;margin:0 auto;padding-top:14vh;text-align:center}
    .nm-load-ring{width:48px;height:48px;margin:0 auto 18px;border:3px solid oklch(0.72 0.10 300/.2);border-top-color:var(--violet-br,oklch(0.80 0.13 300));border-radius:50%;animation:nmspin .9s linear infinite}
    @keyframes nmspin{to{transform:rotate(360deg)}}
    .nm-load-title{font-size:16px;font-weight:700} .nm-load-bar{height:6px;border-radius:4px;background:oklch(0.2 0.02 290);overflow:hidden;margin:14px 0 8px}
    .nm-load-bar>div{height:100%;background:linear-gradient(90deg,oklch(0.66 0.17 300),oklch(0.72 0.15 38));transition:width .4s}
    .nm-load-hint{font-size:12.5px;color:var(--text-dim)}
    /* result */
    .nm-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}
    .nm-eyebrow{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--signal,oklch(0.80 0.14 72))}
    .nm-title{font-family:var(--font-display,"Hahmlet",serif);font-size:29px;font-weight:600;letter-spacing:-.02em;margin-top:4px}
    .nm-reset{font:inherit;font-size:12px;color:var(--text-dim);background:transparent;border:1px solid oklch(0.72 0.10 300/.22);border-radius:7px;padding:7px 12px;cursor:pointer;flex:none}
    .nm-hero{position:relative;margin-top:15px;background:linear-gradient(135deg,oklch(0.66 0.17 300/.16),oklch(0.66 0.16 30/.08));border:1px solid oklch(0.72 0.10 300/.22);border-radius:16px;padding:20px 22px;overflow:hidden}
    .nm-hero::before{content:"";position:absolute;inset:0 auto 0 0;width:3px;background:linear-gradient(oklch(0.66 0.17 300),oklch(0.72 0.15 38))}
    .nm-hero-lab{font-family:var(--font-mono);font-size:11px;color:var(--text-dim);letter-spacing:.04em;display:flex;align-items:center;gap:8px}
    .nm-hero-answer{font-size:19px;font-weight:700;letter-spacing:-.02em;line-height:1.45;margin-top:10px}
    .nm-hero-answer b{color:var(--violet-br,oklch(0.80 0.13 300))} .nm-coral{color:oklch(0.82 0.12 45)} .nm-violet{color:var(--violet-br,oklch(0.80 0.13 300))} .nm-iv{font-family:var(--font-mono);font-size:12px;color:var(--text-dim)}
    .nm-hero-meta{display:flex;gap:8px;flex-wrap:wrap;margin-top:13px}
    .nm-pill{font-family:var(--font-mono);font-size:11px;color:var(--text-dim);background:oklch(0.12 0.02 290/.6);border:1px solid var(--line,oklch(0.72 0.10 300/.13));padding:4px 10px;border-radius:999px}
    .nm-pill b{color:var(--text);font-weight:600}
    .nm-slab{display:flex;align-items:center;gap:9px;margin:24px 2px 12px;font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-mute,oklch(0.54 0.02 290))}
    .nm-slab::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--violet-br,oklch(0.66 0.17 300));box-shadow:0 0 8px oklch(0.66 0.17 300)}
    .nm-slab .h{margin-left:auto;text-transform:none;letter-spacing:0;font-size:11px}
    .nm-card{background:oklch(0.15 0.02 290/.5);border:1px solid var(--line,oklch(0.72 0.10 300/.13));border-radius:14px;padding:16px 18px}
    .nm-personas{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
    .nm-pm{background:oklch(0.15 0.02 290/.5);border:1px solid var(--line,oklch(0.72 0.10 300/.13));border-radius:13px;padding:14px 15px;display:flex;flex-direction:column;gap:9px}
    .nm-pm-pn{display:flex;align-items:center;gap:7px;flex-wrap:wrap} .nm-pm-pn b{font-size:13.5px;font-weight:600;letter-spacing:-.01em}
    .nm-leaf{font-family:var(--font-mono);font-size:10.5px;color:var(--text-dim);background:oklch(0.18 0.02 290/.5);border:1px solid var(--line,oklch(0.72 0.10 300/.13));padding:3px 7px;border-radius:6px;align-self:flex-start}
    .nm-mnum{font-family:var(--font-mono);font-size:11px;color:var(--text-dim);display:flex;justify-content:space-between}
    .nm-mnum .iv{color:var(--violet-br,oklch(0.80 0.13 300))} .nm-mnum .bv{color:oklch(0.82 0.12 45)}
    .nm-mbar{height:6px;border-radius:4px;overflow:hidden;display:flex;border:1px solid var(--line,oklch(0.72 0.10 300/.13))}
    .nm-mbar .i{background:oklch(0.66 0.17 300)} .nm-mbar .b{background:oklch(0.72 0.15 38)}
    .nm-chips{display:flex;flex-direction:column;gap:5px;margin-top:1px}
    .nm-chip{font-family:var(--font-mono);font-size:10.5px;padding:3px 8px;border-radius:6px;align-self:flex-start}
    .nm-chip.bid{color:var(--violet-br,oklch(0.80 0.13 300));background:oklch(0.66 0.17 300/.16);border:1px solid oklch(0.72 0.10 300/.24)}
    .nm-chip.angle{color:oklch(0.82 0.12 45);background:oklch(0.72 0.15 38/.16);border:1px solid oklch(0.72 0.15 38/.2)}
    .nm-kpi{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
    .nm-kpibox{background:oklch(0.15 0.02 290/.5);border:1px solid var(--line,oklch(0.72 0.10 300/.13));border-radius:12px;padding:14px 13px;text-align:center}
    .nm-kpibox .n{font-family:var(--font-display,"Hahmlet",serif);font-size:22px;font-weight:600;letter-spacing:-.02em;color:var(--violet-br,oklch(0.80 0.13 300))}
    .nm-kpibox .n.sm{font-size:15px} .nm-kpibox .l{font-size:10.5px;color:var(--text-dim);margin-top:5px}
    .nm-kw{background:oklch(0.15 0.02 290/.5);border:1px solid var(--line,oklch(0.72 0.10 300/.13));border-radius:14px;padding:16px 18px;margin-top:10px}
    .nm-kwhead{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
    .nm-kwhead .t{font-family:var(--font-mono);font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--text-dim)}
    .nm-copyall{font-family:var(--font-mono);font-size:11px;padding:5px 12px;background:oklch(0.66 0.17 300/.16);border:1px solid oklch(0.72 0.10 300/.24);color:var(--violet-br,oklch(0.80 0.13 300));border-radius:7px;cursor:pointer}
    .nm-kws{display:flex;flex-wrap:wrap;gap:7px}
    .nm-kwchip{font-family:var(--font-mono);font-size:12px;color:var(--text-dim);background:oklch(0.10 0.015 290/.6);border:1px solid var(--line,oklch(0.72 0.10 300/.13));padding:7px 12px;border-radius:8px;cursor:pointer;display:flex;align-items:center;gap:7px;transition:.15s}
    .nm-kwchip:hover{border-color:var(--violet-br,oklch(0.66 0.17 300));color:var(--text)}
    .nm-kwchip .i{font-size:10px;opacity:.5} .nm-kwchip.seed{color:var(--violet-br,oklch(0.80 0.13 300));border-color:oklch(0.72 0.10 300/.24);background:oklch(0.66 0.17 300/.16)}
    .nm-action{display:flex;align-items:center;gap:14px;margin-top:18px;padding:17px 20px;background:linear-gradient(90deg,oklch(0.66 0.17 300/.16),oklch(0.72 0.15 38/.16));border:1px solid oklch(0.72 0.10 300/.22);border-radius:14px}
    .nm-stepn{font-family:var(--font-mono);font-size:10px;color:oklch(0.82 0.12 45);letter-spacing:.08em;margin-bottom:4px}
    .nm-action b{display:block;font-size:14px;font-weight:700;line-height:1.4}
    .nm-go{margin-left:auto;white-space:nowrap;font:inherit;font-size:12.5px;font-weight:700;color:#fff;background:linear-gradient(135deg,oklch(0.66 0.17 300),oklch(0.6 0.17 320));border:none;border-radius:9px;padding:11px 17px;cursor:pointer}
    .nm-up{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-top:11px;padding:13px 18px;background:oklch(0.12 0.02 290/.5);border:1px solid var(--line,oklch(0.72 0.10 300/.13));border-radius:12px}
    .nm-up span{font-size:11.5px;color:var(--text-dim)}
    .nm-up button{white-space:nowrap;font:inherit;font-size:12px;font-weight:600;color:var(--violet-br,oklch(0.80 0.13 300));background:oklch(0.66 0.17 300/.16);border:1px solid oklch(0.72 0.10 300/.24);border-radius:8px;padding:8px 14px;cursor:pointer}
    .nm-empty{text-align:center;padding:10vh 0;color:var(--text-dim)} .nm-empty strong{color:var(--text)} .nm-empty-hint{font-size:12.5px;margin-top:8px}
    .nm-up-btn{font:inherit;font-size:13px;font-weight:700;color:#fff;background:linear-gradient(135deg,oklch(0.66 0.17 300),oklch(0.6 0.17 320));border:none;border-radius:9px;padding:10px 16px;cursor:pointer}
    @media(max-width:760px){.nm-personas{grid-template-columns:1fr}.nm-kpi{grid-template-columns:1fr 1fr}.nm-action{flex-direction:column;align-items:flex-start}.nm-go{margin-left:0}.nm-input-row{flex-direction:column}}
    `}</style>
  );
}

Object.assign(window, { NormalMode });
